acidanthera / bugtracker

Acidanthera Bugtracker
380 stars 42 forks source link

Possible bug? Mac OS 1st stage boot screen not displayed with UGA video cards #1498

Closed CornCat78 closed 3 years ago

CornCat78 commented 3 years ago

Boot picker is visible but no 1st stage (grey background with Apple logo) boot screen. Screen remains gray immediately after OS selection from boot selection menu. 2nd stage (black screen with Apple logo) appears shortly after. Setting OC boot-args to verbose does result in text being displayed during 1st stage boot.

System: Mac Pro 3,1 GPU: Apple EFI Radeon 7950 OS: Catalina 10.15.7

EFI folder and all logs attached. Archive.zip

Edited to add: video output works correctly on RefindPlus boot picker.

startergo commented 3 years ago

may I have MP3,1 firmware?

https://drive.google.com/file/d/1TtiwXSg3bJHIJHZl0VfFO-t2NcxV4yHU/view

vit9696 commented 3 years ago

@startergo BiosROMDump is empty, I need to firmware binary. Not necessarily clean.

startergo commented 3 years ago

@startergo BiosROMDump is empty, I need to firmware binary. Not necessarily clean.

Not sure if this can help but inside Payload: https://support.apple.com/kb/dl95?locale=en_US there is LOCKED_MP31_006C_05B.fd

CornCat78 commented 3 years ago

@vit9696 have a look at this. Definitely not a clean ROM and was dumped from a patched OS. MP31BootROM.zip

As soon as I get some screen time on the MP3,1 (daughter is using it for school project at the moment), will report results back on your latest binary.

CornCat78 commented 3 years ago

Hmm, maybe it is important which console control mode it is actually (graphics versus text)? @CornCat78 can you redo the logs with this one?

OpenCore-0.6.7-DEBUG.zip

Please see attached logs. image opencore-2021-02-20-154849.txt

vit9696 commented 3 years ago

Hmm, literally nothing.

@dakanji can you actually obtain information from AppleFramebufferInfo in rEFInd and print it to the log? I want you to give a test build to @CornCat78 to confirm that we indeed have working AppleFramebufferInfo in rEFInd and not working in OpenCore. Because otherwise I cannot really explain it. EfiBoot needs either GOP or AppleFramebufferInfo to print XNU output. If the former is unavailable, the latter must be.

The test could locate all the handles of AppleFramebufferInfo and print their params by executing the Info method.

dakanji commented 3 years ago

@vit9696 ... Looking at the OC AppleFramebufferGetInfo function, it looks to be GOP specific.

Can't see how it would return anything but EFI_UNSUPPORTED in the OP's setup since GOP is not present.

Side issue: One of the two EFI_UNSUPPORTED statuses returned should be changed to help 3rd parties figure out what failed. Perhaps this one should be EFI_LOAD_ERROR?

vit9696 commented 3 years ago

This protocol is implemented by Apple by all native GPUs/firmwares we are aware about. It is not GOP-specific and in fact comes from pre-UGA era. OpenCore implementation is for non-Apple firmwares to boot 10.4/10.5 with graphics as it does not support GOP. Therefore the error @CornCat78 has comes from Apple, not us.

dakanji commented 3 years ago

What I meant is that it will never progress beyond this point: https://github.com/acidanthera/OpenCorePkg/blob/5e9f9484d5794b6873285328f4f93e1436fdecb2/Library/OcConsoleLib/FramebufferInfo.c#L62

That is, the gBS->HandleProtocol for &gEfiGraphicsOutputProtocolGuid earlier will always fail when GOP is not present on the ConsoleOut Handle, such as MacPro3,1, wouldn't it?

vit9696 commented 3 years ago

AppleFramebufferGetInfo is never called. Read carefully what I wrote you.

dakanji commented 3 years ago

AppleFramebufferGetInfo is never called.

Then I guess I was paddling up the wrong creek in trying to figure out how to get the AppleFramebuffer Info in RP.

The function name seemed to suggest it was one to look at.

vit9696 commented 3 years ago

Hrm. Do you have gAppleFramebufferInfoProtocolGuid installed with rEFInd? The idea is that this protocol is installed by the GPU driver (or perhaps Apple firmware). I assumed the only instance available is installed by AMD GOP. Maybe I am wrong for whatever reason and it actually is ours?

dakanji commented 3 years ago

AppleFramebuffer does not appear, by itself or as part of a longer word, anywhere in the entire code base.

vit9696 commented 3 years ago

Codebase? Sorry? It is a protocol you locate (i.e. that is provided to you by the firmware), just like GOP. It is used by EfiBoot as I shew above, so the point is to check for its existence in the firmware.

vit9696 commented 3 years ago

@CornCat78 in addition to our discussion with @dakanji (wherever it goes and whatever tests do appear) please test the latest master build: https://github.com/acidanthera/OpenCorePkg/runs/1943255158 (will be uploaded shortly). I am starting to wonder whether we install FB Info by accident now.

dakanji commented 3 years ago

i understand. What I meant was that RP does not call on it anywhere. I suppose I can specify the GUID (since not currently existing) and try to locate it.

You had this earlier in https://github.com/acidanthera/bugtracker/issues/1498#issuecomment-782528338 which I suppose I can use:

Status = gBS->LocateProtocol(&gAppleFramebufferInfoProtocolGuid, 0i64, (void **)&FramebufferInfo);

I got the GUID value for gAppleFramebufferInfoProtocolGuid but can you tell me how to define the FramebufferInfo variable? What type should it be?

Looking at the OC code, it seems to be APPLE_FRAMEBUFFER_INFO_PROTOCOL.

I found a declaration:

STATIC
APPLE_FRAMEBUFFER_INFO_PROTOCOL
mAppleFramebufferInfo = {
  AppleFramebufferGetInfo
};

Which was what led me to AppleFramebufferGetInfoin the first place as it seemed to be used to fill up the struct:

typedef
EFI_STATUS
(EFIAPI *APPLE_FRAMEBUFFER_INFO_GET_INFO) (
  IN   APPLE_FRAMEBUFFER_INFO_PROTOCOL  *This,
  OUT  EFI_PHYSICAL_ADDRESS             *FramebufferBase,
  OUT  UINT32                           *FramebufferSize,
  OUT  UINT32                           *ScreenRowBytes,
  OUT  UINT32                           *ScreenWidth,
  OUT  UINT32                           *ScreenHeight,
  OUT  UINT32                           *ScreenDepth
  );
vit9696 commented 3 years ago

@dakanji, yes, the point was to check whether it exists in MacEFI when booted with RP, assuming that OC and RP trigger different MacEFI mechaniasms. The header is here.

I think I did discover the problem after opening a newer EfiBoot in IDA. Apparently there is one more way to detect framebuffer base in modern EfiBoot versions. A new protocol actually. Installing AppleFramebufferInfo will skip this protocol, however, and I believe this is exactly what happens. @CornCat78 GPU exposes framebuffer information through that new protocol, which we need to (partly) reverse-engineer, and OpenCore before https://github.com/acidanthera/OpenCorePkg/commit/39605d02be71c8f8c8e4203b482edd8871b057b9 did install a broken AppleFramebufferInfo, which prevented this new protocol from being used.

CornCat78 commented 3 years ago

I think I did discover the problem after opening a newer EfiBoot in IDA. Apparently there is one more way to detect framebuffer base in modern EfiBoot versions. A new protocol actually. Installing AppleFramebufferInfo will skip this protocol, however, and I believe this is exactly what happens. @CornCat78 GPU exposes framebuffer information through that new protocol, which we need to (partly) reverse-engineer, and OpenCore before acidanthera/OpenCorePkg@39605d0 did install a broken AppleFramebufferInfo, which prevented this new protocol from being used.

@vit9696 given the above, do you still want me to test the latest master build at https://github.com/acidanthera/OpenCorePkg/runs/1943255158, or hold off for the time being?

vit9696 commented 3 years ago

@CornCat78, yes, I do. Master has all the basic needed.

The other protocol actually is related to screen rotation, so it has nothing to do with framebuffer base. All my previous questions hold. Including the RP test. CC @dakanji

CornCat78 commented 3 years ago

@vit9696 just updated to the latest binary provided in your link: image Unfortunately, OC loading stopped and stated halting on critical error before 1st stage boot screen. Log is truncated due to forced reboot. See attached.

20210220_211826_HDR

opencore-2021-02-21-021758.txt

startergo commented 3 years ago

@vit9696 just updated to the latest binary provided in your link: image Unfortunately, OC loading stopped and stated halting on critical error before 1st stage boot screen. Log is truncated due to forced reboot. See attached.

20210220_211826_HDR

opencore-2021-02-21-021758.txt

There are 2 errors in the config. One is in PlatformNVRAM and the other in Output (GopPassthrough is not a valid option for this commit) . I would suggest you use the ocvalidate for this commit to check the config file.

VIT: hid screens

vit9696 commented 3 years ago

Ugh, disregard what I wrote earlier. Just update to master again. There was a mistake. No real need to update the config, warnings are harmless.

dakanji commented 3 years ago

@startergo ... Do you mind deleting the quoted portion with the multiple attachments? Your post by itself is enough to get your message.

vit9696 commented 3 years ago

@dakanji I am done reversing the new EfiBoot additions, actually this is just rotation support. So the function now looks like this, and still there are only two ways to get a framebuffer address: from GOP and from AppleFramebufferInfo.

Since we clearly know that there is no GOP, then there must be AppleFramebufferInfo for 1st stage to work. Question is, who does install this protocol for RP (well, obviously it must be the firmware) and when does it happen. So I need you to add logging like the one I pasted below to different places test it on @CornCat78's computer, and tell me what is going on.

// local variable allocation has failed, the output may be wrong!
void __fastcall GetVideoInfo(Boot_Video *VideoInfo, UINT32 *a2)
{
  EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode; // rax
  EFI_PHYSICAL_ADDRESS FrameBufferBase; // rcx
  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; // rdi
  unsigned int BitDepth; // eax
  EFI_GUID GraphicsInfo; // [rsp+40h] [rbp-40h] BYREF
  APPLE_FRAMEBUFFER_INFO_PROTOCOL *FramebufferInfo; // [rsp+50h] [rbp-30h] BYREF
  EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop; // [rsp+58h] [rbp-28h] BYREF
  APPLE_DISPLAY_INFO_PROTOCOL *DisplayInfo; // [rsp+60h] [rbp-20h] BYREF
  UINT32 Rotation; // [rsp+6Ch] [rbp-14h] OVERLAPPED BYREF

  FramebufferInfo = 0i64;
  Gop = 0i64;
  DisplayInfo = 0i64;
  Rotation = 0xAAAAAAAA;
  GraphicsInfo = gAppleGraphicsInfoProtocolGuid;
  if ( a2 )
    *a2 = dword_9230C;
  if ( !gScreenFrameBufferBase )
  {
    if ( (gBS->HandleProtocol(*(EFI_HANDLE *)(qword_96CC8 + 56), &gEfiGraphicsOutputProtocolGuid, (void **)&Gop) & 0x8000000000000000ui64) == 0i64
      && (Mode = Gop->Mode, (FrameBufferBase = Mode->FrameBufferBase) != 0) )
    {
      Info = Mode->Info;
      gScreenWidth = Info->HorizontalResolution;
      gScreenHeight = Info->VerticalResolution;
      gScreenFrameBufferBase = FrameBufferBase;
      gScreenFrameBufferSize = Mode->FrameBufferSize;
      BitDepth = DetectDepth(Info);
      gScreenBitDepth = BitDepth;
      if ( !BitDepth )
      {
        gScreenFrameBufferBase = 0i64;
        return;
      }
      gScreenPixelBytes = Info->PixelsPerScanLine * (BitDepth >> 3);
    }
    else
    {
      if ( (gBS->LocateProtocol(&gAppleFramebufferInfoProtocolGuid, 0i64, (void **)&FramebufferInfo) & 0x8000000000000000ui64) != 0i64
        || !FramebufferInfo )
      {
        return;
      }
      if ( FramebufferInfo->GetInfo(
             FramebufferInfo,
             &gScreenFrameBufferBase,
             &gScreenFrameBufferSize,
             &gScreenPixelBytes,
             &gScreenWidth,
             &gScreenHeight,
             &gScreenBitDepth) < 0 )
      {
        gScreenFrameBufferBase = 0i64;
        gScreenPixelBytes = 0;
        gScreenWidth = 0;
        gScreenHeight = 0;
        gScreenBitDepth = 0;
      }
    }
  }
  Rotation = 0;
  if ( (gBS->LocateProtocol(&GraphicsInfo, 0i64, (void **)&DisplayInfo) & 0x8000000000000000ui64) == 0i64
    && DisplayInfo->Revision >= 0x10002
    && (DisplayInfo->GetRotation(DisplayInfo, &Rotation) & 0x8000000000000000ui64) != 0i64 )
  {
    Rotation = 0;
  }
  if ( VideoInfo )
  {
    VideoInfo->v_baseAddr = gScreenFrameBufferBase;
    VideoInfo->v_rowBytes = gScreenPixelBytes;
    VideoInfo->v_width = gScreenWidth;
    VideoInfo->v_height = gScreenHeight;
    VideoInfo->v_depth = gScreenBitDepth;
    VideoInfo->v_rotate = Rotation;
  }
}
EFI_STATUS
DumpAppleFramebufferInfo (
  VOID
  )
{
  EFI_STATUS                       Status;
  EFI_HANDLE                       *HandleBuffer;
  UINTN                            HandleCount;
  UINTN                            Index;
  APPLE_FRAMEBUFFER_INFO_PROTOCOL  *FramebufferInfo;
  EFI_PHYSICAL_ADDRESS             FramebufferBase;
  UINT32                           FramebufferSize;
  UINT32                           ScreenRowBytes;
  UINT32                           ScreenWidth;
  UINT32                           ScreenHeight;
  UINT32                           ScreenDepth;

  Status = gBS->LocateHandleBuffer (
    ByProtocol,
    &gAppleFramebufferInfoProtocolGuid,
    NULL,
    &HandleCount,
    &HandleBuffer
    );
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_INFO, "OCC: Failed to find handles with Apple FB Info - %r\n", Status));
    gBS->FreePool (HandleBuffer);
    return Status;
  }

  DEBUG ((DEBUG_INFO, "OCC: Found %u handles with Apple FB Info\n", (UINT32) HandleCount));
  for (Index = 0; Index < HandleCount; ++Index) {
    FramebufferBase = 0;
    FramebufferSize = 0;
    ScreenRowBytes  = 0;

    Status = gBS->HandleProtocol (
      HandleBuffer[Index],
      &gAppleFramebufferInfoProtocolGuid,
      (VOID **) &FramebufferInfo
      );
    if (EFI_ERROR (Status)) {
      DEBUG ((
        DEBUG_INFO,
        "OCC: Failed to retrieve AppleFramebufferInfo protocol on handle %u - %p (%r)\n",
        (UINT32) Index,
        HandleBuffer[Index],
        Status
        ));
    } else {
      DEBUG ((
        DEBUG_INFO,
        "OCC: Got AppleFramebufferInfo protocol on handle %u - %p\n",
        (UINT32) Index,
        HandleBuffer[Index]
        ));

      Status = FramebufferInfo->GetInfo (
        FramebufferInfo,
        &FramebufferBase,
        &FramebufferSize,
        &ScreenRowBytes,
        &ScreenWidth,
        &ScreenHeight,
        &ScreenDepth
        );
      if (!EFI_ERROR (Status)) {
        DEBUG ((
          DEBUG_INFO,
          "OCC: AppleFramebufferInfo - Got Base %Lx, Size %u, RowBytes %u, Width %u, Height %u, Depth %u on handle %u - %p\n",
          FramebufferBase,
          FramebufferSize,
          ScreenRowBytes,
          ScreenWidth,
          ScreenHeight,
          ScreenDepth,
          (UINT32) Index,
          HandleBuffer[Index]
          ));
      } else {
        DEBUG ((
          DEBUG_INFO,
          "OCC: Failed to get info from AppleFramebufferInfo protocol on handle %u - %p (%r)\n",
          (UINT32) Index,
          HandleBuffer[Index],
          Status
          ));
      }
    }
  }

  gBS->FreePool (HandleBuffer);
  return EFI_SUCCESS;
}
dakanji commented 3 years ago

On my cMP3,1 running an RX 580 which has GOP, I get no AppleFramebuffer as at just before calling a loader: Screen Shot 2021-02-21 at 13 12 18

Injected Code ``` VOID QueryAppleFbInfo ( VOID ) { EFI_STATUS Status; UINTN HandleCount = 0; EFI_HANDLE *HandleBuffer = NULL; EFI_GUID gAppleFramebufferInfoProtocolGuid = APPLE_FRAMEBUFFER_INFO_PROTOCOL_GUID; APPLE_FRAMEBUFFER_INFO_PROTOCOL *FramebufferInfo; Status = gBS->LocateProtocol ( &gAppleFramebufferInfoProtocolGuid, NULL, (VOID *) &FramebufferInfo ); if (EFI_ERROR (Status)) { HandleCount = 0; } else { Status = gBS->LocateHandleBuffer ( ByProtocol, &gAppleFramebufferInfoProtocolGuid, NULL, &HandleCount, &HandleBuffer ); if (EFI_ERROR (Status)) { HandleCount = 0; } } if (HandleCount == 1) { MsgLog ("INFO: Found '%d' Apple FrameBuffer Instance\n\n", HandleCount); } else { MsgLog ("INFO: Found '%d' Apple FrameBuffer Instances\n\n", HandleCount); } //for (i = 0; i < HandleCount; i++) { // //} MyFreePool (HandleBuffer); } ```

I could move it later (to just before the actual load image call) but doubt the result will change.

Probably will be the same for the OP don't you think?

vit9696 commented 3 years ago

AppleFramebufferInfo is unique for UGA cards. Mac GOP GPUs may not have it, and any non-Mac GPUs will not have it for sure as it is Apple-specific.

Without both GOP and AppleFramebufferInfo 1st stage cannot display anything, I am quite certain. Thus for @CornCat78 at least something must be present with RP.

dakanji commented 3 years ago

OK, @CornCat78 ... please run the attached X108 file and let's see the log to make a call on how to explore further.

CornCat78 commented 3 years ago

Hello @dakanji . Please see attached log output based on X108 as requested. 21d21k1309.log

vit9696 commented 3 years ago

@CornCat78 and the test with master OC? It all sums up :D

@dakanji see?

 12:385   0:019  INFO: Found '1' Apple FrameBuffer Instance

That's what we do not have I believe in OC.

CornCat78 commented 3 years ago

@vit9696 sorry, can you send me the link of the updated master? The URL I have goes back to the binary compiled yesterday at 20:33 EST.

vit9696 commented 3 years ago

Sure: https://github.com/acidanthera/OpenCorePkg/runs/1945453457

dakanji commented 3 years ago

@CornCat78 ... please run X109 and attach the log. Should point towards where the framebuffer is provided

X109-BOOTx64.efi.zip

CornCat78 commented 3 years ago

opencore-2021-02-21-121035.txt @vit9696 updated to latest master, and still got a halt on critical error. Despite you saying earlier that config doesn't need to be changed, perhaps i should disable GopPassThrough as suggested by @startergo ? 20210221_071110_HDR

vit9696 commented 3 years ago

Well, log? The log file contains why it did halt.Onscreen messages do not.

CornCat78 commented 3 years ago

Sorry, still haven't had my coffee. Previous message edited to include latest log.

CornCat78 commented 3 years ago

@dakanji please see attached RP log for X109. 21d21m2011.log

vit9696 commented 3 years ago

@CornCat78 my bad, forgot to fix one more place. Check OpenCore-2513487c-NOOPT.zip

CornCat78 commented 3 years ago

@vit9696 OK that worked. Please see attached logs. opencore-2021-02-21-123432.txt

vit9696 commented 3 years ago

Bah. God. Now I do see see what the problem is. You have AppleFramebufferInfo = YES in protocol overrides. You definitely should not do this for Macs. If you disable that option, even 0.6.6 would work fine to a certain extent.

Please try 0.6.6 with AppleFramebufferInfo disable disabled. Also try whether OpenCanopy works with 0.6.6 or with the build I gave you.

CornCat78 commented 3 years ago

@vit9696 good grief, you're right. Disabling AppleFramebufferInfo fixed it. Just booted with 0.6.6 and OC displays 1st stage boot screen.

@dakanji , this was preset in overrides by MyBootMgr. Perhaps next iteration can provide the user with an option to enable/disable based on UGA card presence during configuration?

Now I feel horrible for taking up everyone's time on this issue.

vit9696 commented 3 years ago

@CornCat78, well, GOP pass-through will likely be needed for OpenCanopy to work, thus the question of mine.

CornCat78 commented 3 years ago

Sorry, here are the logs from v066 just so everyone can see. opencore-2021-02-21-124821.txt 21d21m4804.log

@vit9696 - will test with OpenCanopy. Will revert back with results shortly.

dakanji commented 3 years ago

You have AppleFramebufferInfo = YES in protocol overrides. You definitely should not do this for Macs.

The documentation does not indicate this and actually seems to suggest it is desirable being switched on.

Screen Shot 2021-02-21 at 15 58 02

vit9696 commented 3 years ago

Well, with GOP GPUs it may, but this is UGA. I changed this to do nothing when no GOP is available in 0.6.7 anyway...

CornCat78 commented 3 years ago

@vit9696 unfortunately halted on critical error with OpenCanopy installed. Perhaps it's something with config.plist? Attaching that as well as logs here. opencore-2021-02-21-130426.txt

config.plist.zip

P.S. took the resources folder from https://github.com/acidanthera/OcBinaryData and copied to EFI/OC. All files should be in the correct position. image

vit9696 commented 3 years ago

Good. For this to work (as well as FileVault 2) you need GopPassThrough (not included in the build above). Please check OpenCore-65aa4eda-NOOPT.zip for both OpenCanopy and 1st stage. If both work fine, also check FV2 (could do later).

CornCat78 commented 3 years ago

@vit9696 so good news and bad news. Good news is that OpenCanopy works: 20210221_081747 Bad news is that while 1st stage boot screen also appears, the Apple logo oddly has disappeared. Only thing visible is the horizontal loading bar. 20210221_081854 Logs attached for review. opencore-2021-02-21-131657.txt

vit9696 commented 3 years ago

Hmmm. Is this consistent? Could you try this version: OpenCore-65aa4eda-NOOPT-T1.zip?

vit9696 commented 3 years ago

Also, please try SystemGeneric renderer with both T1 and the previous build.

CornCat78 commented 3 years ago

T1 build works. OpenCanopy loads and 1st stage boot screen is complete: image Give me a few minutes to test and revert on the SystemGeneric renderer.

Logs for T1 attached below. opencore-2021-02-21-133444.txt