Skip to content

Commit

Permalink
Compress firmware
Browse files Browse the repository at this point in the history
Signed-off-by: Visual Ehrmanntraut <[email protected]>
  • Loading branch information
VisualEhrmanntraut committed Oct 21, 2023
1 parent 18739bc commit 7079e57
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 29 deletions.
8 changes: 8 additions & 0 deletions NootedRed.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

/* Begin PBXBuildFile section */
1C748C2D1C21952C0024EED2 /* PluginStart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C748C2C1C21952C0024EED2 /* PluginStart.cpp */; };
4002B2682AE478AA00B40D3B /* ZlibAlloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4002B2662AE478AA00B40D3B /* ZlibAlloc.cpp */; };
4002B2692AE478AA00B40D3B /* ZlibAlloc.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 4002B2672AE478AA00B40D3B /* ZlibAlloc.hpp */; };
4019EAE42A348852008D800B /* DYLDPatches.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 4019EAE32A348852008D800B /* DYLDPatches.hpp */; };
4019EAE62A3488ED008D800B /* DYLDPatches.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4019EAE52A3488EC008D800B /* DYLDPatches.cpp */; };
40364DB629B79DFD0070A2B4 /* Model.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 40364DB529B79DFD0070A2B4 /* Model.hpp */; };
Expand Down Expand Up @@ -48,6 +50,8 @@
1C748C271C21952C0024EED2 /* NootedRed.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NootedRed.kext; sourceTree = BUILT_PRODUCTS_DIR; };
1C748C2C1C21952C0024EED2 /* PluginStart.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PluginStart.cpp; sourceTree = "<group>"; };
1C748C2E1C21952C0024EED2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4002B2662AE478AA00B40D3B /* ZlibAlloc.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ZlibAlloc.cpp; sourceTree = "<group>"; };
4002B2672AE478AA00B40D3B /* ZlibAlloc.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ZlibAlloc.hpp; sourceTree = "<group>"; };
4019EAE32A348852008D800B /* DYLDPatches.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DYLDPatches.hpp; sourceTree = "<group>"; };
4019EAE52A3488EC008D800B /* DYLDPatches.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DYLDPatches.cpp; sourceTree = "<group>"; };
40364DB529B79DFD0070A2B4 /* Model.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Model.hpp; sourceTree = "<group>"; };
Expand Down Expand Up @@ -187,6 +191,8 @@
40FC5FE029BF9E2500367F9D /* X6000.hpp */,
40FC5FD329BF995000367F9D /* X6000FB.cpp */,
40FC5FD429BF995000367F9D /* X6000FB.hpp */,
4002B2662AE478AA00B40D3B /* ZlibAlloc.cpp */,
4002B2672AE478AA00B40D3B /* ZlibAlloc.hpp */,
);
path = NootedRed;
sourceTree = "<group>";
Expand Down Expand Up @@ -302,6 +308,7 @@
CEA03B5F20EE825A00BA842F /* NRed.hpp in Headers */,
40FC5FD629BF995000367F9D /* X6000FB.hpp in Headers */,
40FC5FDE29BF996900367F9D /* HWLibs.hpp in Headers */,
4002B2692AE478AA00B40D3B /* ZlibAlloc.hpp in Headers */,
4019EAE42A348852008D800B /* DYLDPatches.hpp in Headers */,
4068898C2A229BF600028D22 /* PatcherPlus.hpp in Headers */,
6C1B36672A407C6200B184DD /* HDMI.hpp in Headers */,
Expand Down Expand Up @@ -411,6 +418,7 @@
408F2020288ACBE6002EEC15 /* Firmware.cpp in Sources */,
4068898B2A229BF600028D22 /* PatcherPlus.cpp in Sources */,
40FC5FE129BF9E2500367F9D /* X6000.cpp in Sources */,
4002B2682AE478AA00B40D3B /* ZlibAlloc.cpp in Sources */,
CEA03B5E20EE825A00BA842F /* NRed.cpp in Sources */,
CE405ED91E4A080700AA0B3D /* plugin_start.cpp in Sources */,
40FC5FD929BF995E00367F9D /* X5000.cpp in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion NootedRed/DYLDPatches.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void DYLDPatches::processPatcher(KernelPatcher &patcher) {
if (entry) {
DBGLOG("DYLD", "Setting hwgva-id to iMacPro1,1");
entry->setProperty("hwgva-id", const_cast<char *>(kHwGvaId), arrsize(kHwGvaId));
entry->release();
OSSafeReleaseNULL(entry);
}

KernelPatcher::RouteRequest request {"_cs_validate_page", wrapCsValidatePage, this->orgCsValidatePage};
Expand Down
31 changes: 27 additions & 4 deletions NootedRed/Firmware.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,45 @@
//! See LICENSE for details.

#pragma once
#include "ZlibAlloc.hpp"
#include <Headers/kern_util.hpp>
#include <libkern/c++/OSData.h>
#include <libkern/zlib.h>

struct FWDescriptor {
const char *name;
const UInt8 *data;
const UInt32 size;
const UInt32 compressedSize;
const UInt32 uncompressedSize;
};

#define NRED_FW(name_, data_, size_) .name = name_, .data = data_, .size = size_
#define FIRMWARE(name_, data_, compressedSize_, uncompressedSize_) \
.name = name_, .data = data_, .compressedSize = compressedSize_, .uncompressedSize = uncompressedSize_

extern const struct FWDescriptor firmware[];
extern const size_t firmwareCount;

inline const FWDescriptor &getFWDescByName(const char *name) {
inline OSData *getFWByName(const char *name) {
for (size_t i = 0; i < firmwareCount; i++) {
if (!strcmp(firmware[i].name, name)) { return firmware[i]; }
if (strcmp(firmware[i].name, name)) { continue; }

UInt32 size = firmware[i].uncompressedSize;
auto *dest = reinterpret_cast<Bytef *>(IOMallocZero(size));
z_stream stream = {
.next_in = const_cast<Bytef *>(reinterpret_cast<const Bytef *>(firmware[i].data)),
.avail_in = firmware[i].compressedSize,
.next_out = dest,
.avail_out = size,
.zalloc = ZLibAlloc,
.zfree = ZLibFree,
};
PANIC_COND(inflateInit(&stream) != Z_OK, "FW", "Failed to initialise inflate stream");
auto err = inflate(&stream, Z_FINISH);
PANIC_COND(err != Z_STREAM_END, "FW", "Failed to decompress '%s': %d", name, err);
SYSLOG_COND(inflateEnd(&stream) != Z_OK, "FW", "Failed to end inflate stream");
auto *ret = OSData::withBytes(dest, static_cast<UInt32>(stream.total_out));
IOFree(dest, size);
return ret;
}
PANIC("FW", "'%s' not found", name);
}
File renamed without changes.
20 changes: 12 additions & 8 deletions NootedRed/HWLibs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,21 +203,24 @@ void X5000HWLibs::wrapPopulateFirmwareDirectory(void *that) {
bool isRenoirDerivative = NRed::callback->chipType >= ChipType::Renoir;

auto *filename = isRenoirDerivative ? "ativvaxy_nv.dat" : "ativvaxy_rv.dat";
auto &fwDesc = getFWDescByName(filename);
const auto *vcnFW = getFWByName(filename);
DBGLOG("HWLibs", "VCN firmware filename is %s", filename);

//! VCN 2.2, VCN 1.0
auto *fw = callback->orgCreateFirmware(fwDesc.data, fwDesc.size, isRenoirDerivative ? 0x0202 : 0x0100, filename);
auto *fw = callback->orgCreateFirmware(vcnFW->getBytesNoCopy(), vcnFW->getLength(),
isRenoirDerivative ? 0x0202 : 0x0100, filename);
PANIC_COND(!fw, "HWLibs", "Failed to create '%s' firmware", filename);
//! Can't deallocate, I think. Too bad!
auto *fwDir = getMember<void *>(that, getKernelVersion() > KernelVersion::BigSur ? 0xB0 : 0xB8);
PANIC_COND(!callback->orgPutFirmware(fwDir, 6, fw), "HWLibs", "Failed to insert '%s' firmware", filename);
}

bool X5000HWLibs::wrapGetIpFw(void *that, UInt32 ipVersion, char *name, void *out) {
if (!strncmp(name, "ativvaxy_rv.dat", 16) || !strncmp(name, "ativvaxy_nv.dat", 16)) {
auto &fwDesc = getFWDescByName(name);
getMember<const UInt8 *>(out, 0x0) = fwDesc.data;
getMember<UInt32>(out, 0x8) = fwDesc.size;
const auto *fwDesc = getFWByName(name);
getMember<const void *>(out, 0x0) = fwDesc->getBytesNoCopy();
getMember<UInt32>(out, 0x8) = fwDesc->getLength();
//! Can't deallocate, too bad!
return true;
}
return FunctionCast(wrapGetIpFw, callback->orgGetIpFw)(that, ipVersion, name, out);
Expand Down Expand Up @@ -438,9 +441,10 @@ CAILResult X5000HWLibs::wrapPspCmdKmSubmit(void *ctx, void *cmd, void *param3, v
return FunctionCast(wrapPspCmdKmSubmit, callback->orgPspCmdKmSubmit)(ctx, cmd, param3, param4);
}

auto &fwDesc = getFWDescByName(filename);
memcpy(data, fwDesc.data, fwDesc.size);
getMember<UInt32>(cmd, 0xC) = fwDesc.size;
const auto *fw = getFWByName(filename);
memcpy(data, fw->getBytesNoCopy(), fw->getLength());
getMember<UInt32>(cmd, 0xC) = fw->getLength();
OSSafeReleaseNULL(fw);

return FunctionCast(wrapPspCmdKmSubmit, callback->orgPspCmdKmSubmit)(ctx, cmd, param3, param4);
}
Expand Down
13 changes: 6 additions & 7 deletions NootedRed/NRed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,19 +150,18 @@ void NRed::processPatcher(KernelPatcher &patcher) {

if ((lilu.getRunMode() & LiluAPI::RunningInstallerRecovery) || checkKernelArgument("-CKFBOnly")) { return; }

auto &desc = getFWDescByName("Drivers.xml");
auto *driversXML = getFWByName("Drivers.xml");
driversXML->appendByte(0, 1); //! Null terminator
OSString *errStr = nullptr;
auto *dataNull = new char[desc.size + 1];
memcpy(dataNull, desc.data, desc.size);
dataNull[desc.size] = 0;
auto *dataUnserialized = OSUnserializeXML(dataNull, desc.size + 1, &errStr);
delete[] dataNull;
auto *dataUnserialized = OSUnserializeXML(reinterpret_cast<const char *>(driversXML->getBytesNoCopy()),
driversXML->getLength(), &errStr);
PANIC_COND(!dataUnserialized, "NRed", "Failed to unserialize Drivers.xml: %s",
errStr ? errStr->getCStringNoCopy() : "Unspecified");
auto *drivers = OSDynamicCast(OSArray, dataUnserialized);
PANIC_COND(!drivers, "NRed", "Failed to cast Drivers.xml data");
PANIC_COND(!gIOCatalogue->addDrivers(drivers), "NRed", "Failed to add drivers");
dataUnserialized->release();
OSSafeReleaseNULL(dataUnserialized);
OSSafeReleaseNULL(driversXML);
}

OSMetaClassBase *NRed::wrapSafeMetaCast(const OSMetaClassBase *anObject, const OSMetaClass *toMeta) {
Expand Down
4 changes: 2 additions & 2 deletions NootedRed/NRed.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,13 @@ class NRed {
UInt32 size = 256 * 1024; //! ???
if (!checkAtomBios(fb, size)) {
DBGLOG("NRed", "VRAM VBIOS is not an ATOMBIOS");
bar0->release();
OSSafeReleaseNULL(bar0);
return false;
}
this->vbiosData = OSData::withBytes(fb, size);
PANIC_COND(UNLIKELY(!this->vbiosData), "NRed", "VRAM OSData::withBytes failed");
this->iGPU->setProperty("ATY,bin_image", this->vbiosData);
bar0->release();
OSSafeReleaseNULL(bar0);
return true;
}

Expand Down
10 changes: 7 additions & 3 deletions NootedRed/X5000.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,11 @@ void X5000::wrapSetupAndInitializeHWCapabilities(void *that) {
bool isRavenDerivative = NRed::callback->chipType < ChipType::Renoir;
char filename[128] = {0};
snprintf(filename, arrsize(filename), "%s_gpu_info.bin", isRavenDerivative ? NRed::getChipName() : "renoir");
auto &fwDesc = getFWDescByName(filename);
auto *header = reinterpret_cast<const CommonFirmwareHeader *>(fwDesc.data);
auto *gpuInfo = reinterpret_cast<const GPUInfoFirmware *>(fwDesc.data + header->ucodeOff);
const auto *gpuInfoBin = getFWByName(filename);
auto *header =
reinterpret_cast<const CommonFirmwareHeader *>(gpuInfoBin->getBytesNoCopy(0, sizeof(CommonFirmwareHeader)));
auto *gpuInfo = reinterpret_cast<const GPUInfoFirmware *>(
gpuInfoBin->getBytesNoCopy(header->ucodeOff, sizeof(GPUInfoFirmware)));

auto catalina = getKernelVersion() == KernelVersion::Catalina;
setHWCapability<UInt32>(that, catalina ? HWCapabilityCatalina::SECount : HWCapability::SECount, gpuInfo->gcNumSe);
Expand All @@ -225,6 +227,8 @@ void X5000::wrapSetupAndInitializeHWCapabilities(void *that) {
setHWCapability<UInt32>(that, catalina ? HWCapabilityCatalina::CUPerSH : HWCapability::CUPerSH,
gpuInfo->gcNumCuPerSh);

OSSafeReleaseNULL(gpuInfoBin);

FunctionCast(wrapSetupAndInitializeHWCapabilities, callback->orgSetupAndInitializeHWCapabilities)(that);

setHWCapability<UInt32>(that, catalina ? HWCapabilityCatalina::DisplayPipeCount : HWCapability::DisplayPipeCount,
Expand Down
2 changes: 1 addition & 1 deletion NootedRed/X6000FB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ void X6000FB::registerDispMaxBrightnessNotif() {
callback->dispNotif =
IOService::addMatchingNotification(gIOFirstMatchNotification, matching, OnAppleBacklightDisplayLoad, nullptr);
SYSLOG_COND(!callback->dispNotif, "X6000FB", "registerDispMaxBrightnessNotif: Failed to register notification");
matching->release();
OSSafeReleaseNULL(matching);
}

UInt32 X6000FB::wrapDcePanelCntlHwInit(void *panelCntl) {
Expand Down
19 changes: 19 additions & 0 deletions NootedRed/ZlibAlloc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//! Copyright © 2022-2023 ChefKiss Inc. Licensed under the Thou Shalt Not Profit License version 1.5.
//! See LICENSE for details.

#include "ZlibAlloc.hpp"

void *ZLibAlloc(void *, UInt32 items, UInt32 size) {
UInt32 allocSize = items * size + sizeof(UInt32);
auto *mem = static_cast<UInt32 *>(IOMallocZero(allocSize));

if (!mem) { return nullptr; }

*mem = allocSize;
return mem + 1;
}

void ZLibFree(void *, void *ptr) {
auto *mem = static_cast<UInt32 *>(ptr) - 1;
IOFree(mem, *mem);
}
9 changes: 9 additions & 0 deletions NootedRed/ZlibAlloc.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//! Copyright © 2022-2023 ChefKiss Inc. Licensed under the Thou Shalt Not Profit License version 1.5.
//! See LICENSE for details.

#pragma once
#include <IOKit/IOLib.h>
#include <IOKit/IOTypes.h>

void *ZLibAlloc(void *opaque, UInt32 items, UInt32 size);
void ZLibFree(void *opaque, void *ptr);
10 changes: 7 additions & 3 deletions Scripts/GenerateFirmware.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/python3

import zlib
import os
import struct
import sys
Expand All @@ -19,6 +20,8 @@ def format_file_name(file_name):
def lines_for_file(path, file):
with open(path, "rb") as src_file:
src_data = src_file.read()
src_len_uncompressed = len(src_data)
src_data = zlib.compress(src_data)
src_len = len(src_data)

lines: list[str] = []
Expand All @@ -40,21 +43,22 @@ def lines_for_file(path, file):
.format(*struct.unpack("BBBBBBBBBBBBBBBB", block)))
return lines + [
"};\n",
f"const long int {fw_var_name}_size = sizeof({fw_var_name});\n",
f"const UInt32 {fw_var_name}_compressedSize = sizeof({fw_var_name});\n",
f"const UInt32 {fw_var_name}_uncompressedSize = {src_len_uncompressed};\n",
]


def process_files(target_file, dir):
os.makedirs(os.path.dirname(target_file), exist_ok=True)
lines: list[str] = header.splitlines(keepends=True)
files = list(filter(lambda v: not os.path.basename(v[1]).startswith('.'), [
files = list(filter(lambda v: not os.path.basename(v[1]).startswith('.') and not os.path.basename(v[1]) == "LICENSE", [
(root, file) for root, _, files in os.walk(dir) for file in files]))
file_list_content: list[str] = []
for root, file in files:
lines += lines_for_file(os.path.join(root, file), file)
fw_var_name = format_file_name(file)
file_list_content += [
f" {{NRED_FW(\"{file}\", {fw_var_name}, {fw_var_name}_size)}},\n"]
f" {{FIRMWARE(\"{file}\", {fw_var_name}, {fw_var_name}_compressedSize, {fw_var_name}_uncompressedSize)}},\n"]

lines += ["\n", "const struct FWDescriptor firmware[] = {\n"]
lines += file_list_content
Expand Down

0 comments on commit 7079e57

Please sign in to comment.