Skip to content

Commit

Permalink
feat: Also read VBIOS from PCI Expansion ROM
Browse files Browse the repository at this point in the history
  • Loading branch information
VisualEhrmanntraut committed Oct 18, 2024
1 parent 122b0fe commit fd580fe
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 30 deletions.
6 changes: 5 additions & 1 deletion NootedRed/AMDCommon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ struct CosReadConfigurationSettingOutput {

//-------- AMD Catalyst Constants --------//

constexpr UInt64 DEVICE_CAP_ENTRY_REV_DONT_CARE = 0xDEADCAFEU;
constexpr UInt64 DEVICE_CAP_ENTRY_REV_DONT_CARE = 0xDEADCAFE;

constexpr UInt32 PP_RESULT_OK = 1;

Expand All @@ -392,6 +392,10 @@ static const UInt32 ddiCapsRenoir[16] = {0x800005, 0x500011FE, 0x80000, 0x110010

static const UInt32 ravenDevAttrFlags = 0x49;

constexpr UInt32 ATOMBIOS_IMAGE_SIZE = 0x10000;

//-------- Display Core Constants --------//

constexpr UInt32 DC_SIGNAL_TYPE_LVDS = 0x8;
constexpr UInt32 DC_SIGNAL_TYPE_EDP = 0x80;

Expand Down
2 changes: 1 addition & 1 deletion NootedRed/AppleGFXHDA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ void AppleGFXHDA::init() {

bool AppleGFXHDA::processKext(KernelPatcher &patcher, size_t id, mach_vm_address_t slide, size_t size) {
if (kextAppleGFXHDA.loadIndex == id) {
NRed::callback->ensureRMMIO();
NRed::callback->hwLateInit();

const UInt32 probeFind = Navi10HDMIID;
const UInt32 probeRepl = NRed::callback->attributes.isRenoir() ? RenoirHDMIID : RavenHDMIID;
Expand Down
2 changes: 1 addition & 1 deletion NootedRed/HWLibs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ void X5000HWLibs::init() {

bool X5000HWLibs::processKext(KernelPatcher &patcher, size_t id, mach_vm_address_t slide, size_t size) {
if (kextRadeonX5000HWLibs.loadIndex == id) {
NRed::callback->ensureRMMIO();
NRed::callback->hwLateInit();

CAILAsicCapsEntry *orgCapsTable;
CAILAsicCapsInitEntry *orgCapsInitTable;
Expand Down
89 changes: 66 additions & 23 deletions NootedRed/NRed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ void NRed::processPatcher(KernelPatcher &patcher) {
this->pciRevision = WIOKit::readPCIConfigValue(NRed::callback->iGPU, WIOKit::kIOPCIConfigRevisionID);

SYSLOG_COND(this->iGPU->getProperty("model") != nullptr, "NRed",
"WARNING!!! Attempted to manually override the model, this is no longer supported!!");
"WARNING!!! Overriding the model is no longer supported!");

auto *model = getBranding(this->deviceID, this->pciRevision);
auto modelLen = static_cast<UInt32>(strlen(model) + 1);
Expand All @@ -181,24 +181,6 @@ void NRed::processPatcher(KernelPatcher &patcher) {
}
}

auto *prop = OSDynamicCast(OSData, this->iGPU->getProperty("ATY,bin_image"));
if (prop == nullptr) {
if (!this->getVBIOSFromVFCT()) {
SYSLOG("NRed", "Failed to get VBIOS from VFCT, trying to get it from VRAM!");
PANIC_COND(!this->getVBIOSFromVRAM(), "NRed", "Failed to get VBIOS!");
}
} else {
SYSLOG("NRed", "WARNING!!! VBIOS MANUALLY OVERRIDDEN, ONLY DO THIS IF YOU KNOW WHAT YOU'RE DOING!!");
this->vbiosData = OSData::withBytes(prop->getBytesNoCopy(), prop->getLength());
PANIC_COND(this->vbiosData == nullptr, "NRed", "Failed to allocate VBIOS data!");
}

auto len = this->vbiosData->getLength();
if (len < 65536) {
DBGLOG("NRed", "Padding VBIOS to 65536 bytes (was %u).", len);
this->vbiosData->appendByte(0, 65536 - len);
}

DeviceInfo::deleter(devInfo);

KernelPatcher::RouteRequest requests[] = {
Expand Down Expand Up @@ -306,9 +288,36 @@ OSMetaClassBase *NRed::wrapSafeMetaCast(const OSMetaClassBase *anObject, const O
return nullptr;
}

void NRed::ensureRMMIO() {
void NRed::hwLateInit() {
if (this->rmmio != nullptr) { return; }

auto *atombiosImageProp = OSDynamicCast(OSData, this->iGPU->getProperty("ATY,bin_image"));
if (atombiosImageProp == nullptr) {
if (this->getVBIOSFromExpansionROM()) {
DBGLOG("NRed", "Got VBIOS from PCI Expansion ROM.");
} else {
SYSLOG("NRed", "Failed to get VBIOS from PCI Expansion ROM, trying to get it from VFCT!");
if (this->getVBIOSFromVFCT()) {
DBGLOG("NRed", "Got VBIOS from VFCT.");
} else {
SYSLOG("NRed", "Failed to get VBIOS from VFCT, trying to get it from VRAM!");
PANIC_COND(!this->getVBIOSFromVRAM(), "NRed", "Failed to get VBIOS!");
DBGLOG("NRed", "Got VBIOS from VRAM.");
}
}
this->iGPU->setProperty("ATY,bin_image", this->vbiosData);
} else {
atombiosImageProp->retain();
this->vbiosData = atombiosImageProp;
SYSLOG("NRed", "!!! VBIOS MANUALLY OVERRIDDEN, MAKE SURE YOU KNOW WHAT YOU'RE DOING !!!");
}

auto len = this->vbiosData->getLength();
if (len < ATOMBIOS_IMAGE_SIZE) {
DBGLOG("NRed", "Padding VBIOS to %u bytes (was %u).", ATOMBIOS_IMAGE_SIZE, len);
this->vbiosData->appendByte(0, ATOMBIOS_IMAGE_SIZE - len);
}

this->rmmio =
this->iGPU->mapDeviceMemoryWithRegister(kIOPCIConfigBaseAddress5, kIOMapInhibitCache | kIOMapAnywhere);
PANIC_COND(this->rmmio == nullptr || this->rmmio->getLength() == 0, "NRed", "Failed to map RMMIO");
Expand Down Expand Up @@ -501,6 +510,43 @@ static bool checkAtomBios(const UInt8 *bios, size_t size) {
return false;
}

bool NRed::getVBIOSFromExpansionROM() {
auto expansionROMBase = this->iGPU->extendedConfigRead32(kIOPCIConfigExpansionROMBase);
if (expansionROMBase == 0) {
DBGLOG("NRed", "No PCI Expansion ROM available");
return false;
}

auto *expansionROM =
this->iGPU->mapDeviceMemoryWithRegister(kIOPCIConfigExpansionROMBase, kIOMapInhibitCache | kIOMapAnywhere);
if (expansionROM == nullptr) { return false; }
auto expansionROMLength = min(expansionROM->getLength(), ATOMBIOS_IMAGE_SIZE);
if (expansionROMLength == 0) {
DBGLOG("NRed", "PCI Expansion ROM is empty");
expansionROM->release();
return false;
}

// Enable reading the expansion ROMs
this->iGPU->extendedConfigWrite32(kIOPCIConfigExpansionROMBase, expansionROMBase | 1);

this->vbiosData = OSData::withBytes(reinterpret_cast<const void *>(expansionROM->getVirtualAddress()),
static_cast<UInt32>(expansionROMLength));
PANIC_COND(this->vbiosData == nullptr, "NRed", "PCI Expansion ROM OSData::withBytes failed");
OSSafeReleaseNULL(expansionROM);

// Disable reading the expansion ROMs
this->iGPU->extendedConfigWrite32(kIOPCIConfigExpansionROMBase, expansionROMBase);

if (checkAtomBios(static_cast<const UInt8 *>(this->vbiosData->getBytesNoCopy()), expansionROMLength)) {
return true;
} else {
DBGLOG("NRed", "PCI Expansion ROM VBIOS is not an ATOMBIOS");
OSSafeReleaseNULL(this->vbiosData);
return false;
}
}

// Hack
class AppleACPIPlatformExpert : IOACPIPlatformExpert {
friend class NRed;
Expand Down Expand Up @@ -545,8 +591,6 @@ bool NRed::getVBIOSFromVFCT() {

this->vbiosData = OSData::withBytes(vContent, vHdr->imageLength);
PANIC_COND(this->vbiosData == nullptr, "NRed", "VFCT OSData::withBytes failed");
this->iGPU->setProperty("ATY,bin_image", this->vbiosData);

return true;
}
}
Expand All @@ -571,7 +615,6 @@ bool NRed::getVBIOSFromVRAM() {
}
this->vbiosData = OSData::withBytes(fb, size);
PANIC_COND(this->vbiosData == nullptr, "NRed", "VRAM OSData::withBytes failed");
this->iGPU->setProperty("ATY,bin_image", this->vbiosData);
OSSafeReleaseNULL(bar0);
return true;
}
Expand Down
3 changes: 2 additions & 1 deletion NootedRed/NRed.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class NRed {

void init();
void processPatcher(KernelPatcher &patcher);
void ensureRMMIO();
void hwLateInit();
void processKext(KernelPatcher &patcher, size_t id, mach_vm_address_t slide, size_t size);

const char *getChipName();
Expand All @@ -109,6 +109,7 @@ class NRed {
}

private:
bool getVBIOSFromExpansionROM();
bool getVBIOSFromVFCT();
bool getVBIOSFromVRAM();
UInt32 smuWaitForResponse();
Expand Down
2 changes: 1 addition & 1 deletion NootedRed/X5000.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ void X5000::init() {

bool X5000::processKext(KernelPatcher &patcher, size_t id, mach_vm_address_t slide, size_t size) {
if (kextRadeonX5000.loadIndex == id) {
NRed::callback->ensureRMMIO();
NRed::callback->hwLateInit();

UInt32 *orgChannelTypes;
mach_vm_address_t startHWEngines;
Expand Down
2 changes: 1 addition & 1 deletion NootedRed/X6000.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void X6000::init() {

bool X6000::processKext(KernelPatcher &patcher, size_t id, mach_vm_address_t slide, size_t size) {
if (kextRadeonX6000.loadIndex == id) {
NRed::callback->ensureRMMIO();
NRed::callback->hwLateInit();

void *orgFillUBMSurface, *orgConfigureDisplay, *orgGetDisplayInfo, *orgAllocateScanoutFB;

Expand Down
2 changes: 1 addition & 1 deletion NootedRed/X6000FB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ void X6000FB::init() {

bool X6000FB::processKext(KernelPatcher &patcher, size_t id, mach_vm_address_t slide, size_t size) {
if (kextRadeonX6000Framebuffer.loadIndex == id) {
NRed::callback->ensureRMMIO();
NRed::callback->hwLateInit();

CAILAsicCapsEntry *orgAsicCapsTable;
SolveRequestPlus solveRequest {"__ZL20CAIL_ASIC_CAPS_TABLE", orgAsicCapsTable, kCailAsicCapsTablePattern};
Expand Down

0 comments on commit fd580fe

Please sign in to comment.