mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-11-10 09:40:53 +01:00
Deprecate FIX_HEADERS.
This commit is contained in:
parent
23f0df20ed
commit
bf74520cef
@ -61,7 +61,7 @@ extern "C" int main(int argc, const char * argv[])
|
||||
//path = "/JiefLand/5.Devel/Clover/user config/BS.plist";
|
||||
//path = "/JiefLand/5.Devel/Clover/user config/maclinuxG4/config.plist";
|
||||
//path = "/JiefLand/5.Devel/Clover/user config/MICKHAEL/EFI_Github/CLOVER/config.plist";
|
||||
path = "/JiefLand/5.Devel/Clover/user config/Slice/2021-04-29/config.plist";
|
||||
path = "/JiefLand/5.Devel/Clover/user config/MacKonsti/2021-05-17/config-test.plist";
|
||||
#endif
|
||||
|
||||
if ( !path ) {
|
||||
|
@ -399,7 +399,7 @@ BOOLEAN FixAsciiTableHeader(UINT8 *Str, UINTN Len)
|
||||
BOOLEAN PatchTableHeader(EFI_ACPI_DESCRIPTION_HEADER *Header)
|
||||
{
|
||||
BOOLEAN Ret1, Ret2, Ret3;
|
||||
if (!(gSettings.ACPI.DSDT.FixDsdt & FIX_HEADERS) && !gSettings.ACPI.FixHeaders) {
|
||||
if ( !gSettings.ACPI.FixHeaders ) {
|
||||
return FALSE;
|
||||
}
|
||||
Ret1 = FixAsciiTableHeader((UINT8*)&Header->CreatorId, 4);
|
||||
@ -438,7 +438,7 @@ void PatchAllTables()
|
||||
}
|
||||
EFI_ACPI_DESCRIPTION_HEADER* NewTable = (EFI_ACPI_DESCRIPTION_HEADER*)(UINTN)BufferPtr;
|
||||
CopyMem(NewTable, Table, Len);
|
||||
if ((gSettings.ACPI.DSDT.FixDsdt & FIX_HEADERS) || gSettings.ACPI.FixHeaders) {
|
||||
if ( gSettings.ACPI.FixHeaders ) {
|
||||
// Merged tables already have the header patched, so no need to do it again
|
||||
if (!IsXsdtEntryMerged(IndexFromXsdtEntryPtr(Ptr))) {
|
||||
// table header NOT already patched
|
||||
|
@ -1086,7 +1086,7 @@ public:
|
||||
ResetAddr = configPlist.dgetResetAddr();
|
||||
ResetVal = configPlist.dgetResetVal();
|
||||
SlpSmiEnable = configPlist.dgetSlpSmiEnable();
|
||||
FixHeaders = configPlist.dgetFixHeaders();
|
||||
FixHeaders = configPlist.dgetFixHeaders() || configPlist.DSDT.Fixes.dgetFixHeaders();
|
||||
FixMCFG = configPlist.dgetFixMCFG();
|
||||
NoASPM = configPlist.dgetNoASPM();
|
||||
smartUPS = configPlist.dgetsmartUPS();
|
||||
|
@ -883,7 +883,10 @@ EFI_STATUS ConfigManager::LoadConfig(const XStringW& ConfName)
|
||||
log_technical_bug("%s : !selfOem.isInitialized()", __PRETTY_FUNCTION__);
|
||||
}
|
||||
EFI_STATUS Status = LoadConfigPlist(ConfName);
|
||||
if ( EFI_ERROR(Status) ) return Status;
|
||||
if ( EFI_ERROR(Status) ) {
|
||||
DBG("LoadConfigPlist return %s. Config not loaded\n", efiStrError(Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*Status = */ LoadSMBIOSPlist(L"smbios"_XSW); // we don't need Status. If not loaded correctly, smbiosPlist is !defined and will be ignored by AssignOldNewSettings()
|
||||
|
||||
|
@ -101,6 +101,28 @@ public:
|
||||
|
||||
virtual void getFields(XmlDictField** fields, size_t* nb) override { *fields = m_fields; *nb = sizeof(m_fields)/sizeof(m_fields[0]); };
|
||||
|
||||
virtual bool validate(XmlLiteParser* xmlLiteParser, const XString8& xmlPath, const XmlParserPosition& keyPos, bool generateErrors) override {
|
||||
if ( !super::validate(xmlLiteParser, xmlPath, keyPos, generateErrors) ) return false;
|
||||
if ( !isDefined() ) return true;
|
||||
if ( LString8(ACPI.DSDT.Fixes.ACPI_DSDT_Fixe_Array[29].getNewName()) != "FixHeaders_20000000"_XS8 ) {
|
||||
log_technical_bug("ACPI_DSDT_Fixe_Array[29].getNewName() != \"FixHeaders_20000000\"");
|
||||
}
|
||||
if ( ACPI.getFixHeaders().isDefined() && ACPI.DSDT.Fixes.ACPI_DSDT_Fixe_Array[29].isDefined() ) {
|
||||
if ( ACPI.getFixHeaders().value() == ACPI.DSDT.Fixes.ACPI_DSDT_Fixe_Array[29].dgetEnabled() ) {
|
||||
xmlLiteParser->addWarning(generateErrors, S8Printf("FixHeaders exists in ACPI and ACPI/DSDT/Fixes. Delete FixHeaders from ACPI/DSDT/Fixes."));
|
||||
}else{
|
||||
if ( ACPI.getFixHeaders().value() || ACPI.DSDT.Fixes.ACPI_DSDT_Fixe_Array[29].dgetEnabled() ) {
|
||||
if ( ACPI.getFixHeaders().value() ) {
|
||||
xmlLiteParser->addWarning(generateErrors, S8Printf("FixHeaders exists in ACPI and ACPI/DSDT/Fixes with a different value. Using value of ACPI/FixHeaders. Delete FixHeaders from ACPI/DSDT/Fixes."));
|
||||
}else{
|
||||
xmlLiteParser->addWarning(generateErrors, S8Printf("FixHeaders exists in ACPI and ACPI/DSDT/Fixes with a different value. Using value of ACPI/DSDT/Fixes/FixHeaders. Delete FixHeaders from ACPI/DSDT/Fixes and set ACPI/FixHeaders to true."));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const decltype(DisableDrivers)::ValueType& dgetDisabledDriverArray() const { return DisableDrivers.isDefined() ? DisableDrivers.value() : DisableDrivers.nullValue; };
|
||||
const decltype(SMBIOS)& getSMBIOS() const { return SMBIOS; };
|
||||
|
||||
|
@ -170,6 +170,9 @@ public:
|
||||
if ( dgetResetAddr() == 0xCF9) return 0x06;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const decltype(FixHeaders)& getFixHeaders() const { return FixHeaders; };
|
||||
|
||||
bool dgetSlpSmiEnable() const { return HaltEnabler.isDefined() ? HaltEnabler.value() : false; };
|
||||
bool dgetFixHeaders() const { return FixHeaders.isDefined() ? FixHeaders.value() : false; };
|
||||
bool dgetFixMCFG() const { return FixMCFG.isDefined() ? FixMCFG.value() : false; };
|
||||
|
@ -14,6 +14,11 @@
|
||||
|
||||
XmlAbstractType& ConfigPlistClass::ACPI_Class::DSDT_Class::ACPI_DSDT_Fixes_Class::parseValueFromXmlLite(XmlLiteParser* xmlLiteParser, const XString8& xmlPath, bool generateErrors, const XmlParserPosition &keyPos, const char *keyValue, size_t keyValueLength, bool* keyFound)
|
||||
{
|
||||
#ifdef JIEF_DEBUG
|
||||
if ( strncmp(keyValue, "FixHeaders", strlen("FixHeaders")) == 0 ) {
|
||||
NOP;
|
||||
}
|
||||
#endif
|
||||
for ( size_t idx = 0 ; idx < sizeof(ACPI_DSDT_Fixe_Array)/sizeof(ACPI_DSDT_Fixe_Array[0]) ; idx++ )
|
||||
{
|
||||
if ( ACPI_DSDT_Fixe_Array[idx].getNewName() && strnIsEqualIC(keyValue, keyValueLength, ACPI_DSDT_Fixe_Array[idx].getNewName()) ) {
|
||||
@ -27,6 +32,7 @@ XmlAbstractType& ConfigPlistClass::ACPI_Class::DSDT_Class::ACPI_DSDT_Fixes_Class
|
||||
ACPI_DSDT_Fixe_Array[idx].newEnabled.reset();
|
||||
}
|
||||
ACPI_DSDT_Fixe_Array[idx].newEnabled.parseFromXmlLite(xmlLiteParser, xmlPath, true);
|
||||
ACPI_DSDT_Fixe_Array[idx].setDefined();
|
||||
*keyFound = true;
|
||||
return ACPI_DSDT_Fixe_Array[idx].newEnabled;
|
||||
}else
|
||||
@ -41,6 +47,7 @@ XmlAbstractType& ConfigPlistClass::ACPI_Class::DSDT_Class::ACPI_DSDT_Fixes_Class
|
||||
ACPI_DSDT_Fixe_Array[idx].oldEnabled.reset();
|
||||
}
|
||||
ACPI_DSDT_Fixe_Array[idx].oldEnabled.parseFromXmlLite(xmlLiteParser, xmlPath, true);
|
||||
ACPI_DSDT_Fixe_Array[idx].setDefined();
|
||||
*keyFound = true;
|
||||
return ACPI_DSDT_Fixe_Array[idx].oldEnabled;
|
||||
}
|
||||
|
@ -18,29 +18,33 @@ class DSDT_Class : public XmlDict
|
||||
public:
|
||||
class ACPI_DSDT_Fixes_Class;
|
||||
|
||||
class ACPI_DSDT_Fix : public XmlBool
|
||||
class ACPI_DSDT_Fix : public XmlAbstractType
|
||||
{
|
||||
using super = XmlBool;
|
||||
using super = XmlAbstractType;
|
||||
friend class ACPI_DSDT_Fixes_Class;
|
||||
protected:
|
||||
const CHAR8* m_newName = NULL;
|
||||
const CHAR8* m_oldName = NULL;
|
||||
UINT32 m_bitData = 0;
|
||||
XmlBool oldEnabled = XmlBool();
|
||||
XmlBool newEnabled = XmlBool();
|
||||
XmlBool oldEnabled {};
|
||||
XmlBool newEnabled {};
|
||||
|
||||
public:
|
||||
ACPI_DSDT_Fix(const CHAR8* newName, const CHAR8* oldName, UINT32 bitData ) : XmlBool(), m_newName(newName), m_oldName(oldName), m_bitData(bitData) {};
|
||||
constexpr ACPI_DSDT_Fix(const CHAR8* newName, const CHAR8* oldName, UINT32 bitData ) : m_newName(newName), m_oldName(oldName), m_bitData(bitData), oldEnabled(), newEnabled() {};
|
||||
ACPI_DSDT_Fix(const ACPI_DSDT_Fix&) { panic("copy ctor"); }; // can't do "=delete" because clang thinks it will be called at initialization "ACPI_DSDT_Fixes_Class Fixes = ACPI_DSDT_Fixes_Class();"
|
||||
ACPI_DSDT_Fix& operator = (const ACPI_DSDT_Fix&) = delete; // { panic("copy ctor"); }; // = delete;
|
||||
|
||||
virtual const char* getDescription() override { panic("not defined"); };
|
||||
virtual bool isTheNextTag(XmlLiteParser* xmlLiteParser) override { panic("not defined"); };
|
||||
virtual bool parseFromXmlLite(XmlLiteParser* xmlLiteParser, const XString8& xmlPath, bool generateErrors) override { panic("not defined"); };
|
||||
|
||||
virtual void reset() override {
|
||||
super::reset();
|
||||
oldEnabled.reset();
|
||||
newEnabled.reset();
|
||||
};
|
||||
|
||||
const CHAR8* getNewName() const { return m_newName; }
|
||||
constexpr const CHAR8* getNewName() const { return m_newName; }
|
||||
const CHAR8* getOldName() const { return m_oldName; }
|
||||
uint32_t getBitData() const { return m_bitData; }
|
||||
|
||||
@ -57,7 +61,7 @@ public:
|
||||
class ACPI_DSDT_Fixes_Class : public XmlDict
|
||||
{
|
||||
using super = XmlDict;
|
||||
protected:
|
||||
public:
|
||||
ACPI_DSDT_Fix ACPI_DSDT_Fixe_Array[31] = { // CAREFUL not to declare too much
|
||||
{ "AddDTGP_0001", "AddDTGP", FIX_DTGP },
|
||||
{ "FixDarwin_0002", "FixDarwin", FIX_WARNING },
|
||||
@ -88,7 +92,7 @@ public:
|
||||
{ "FIX_ACST_4000000", "FixACST", FIX_ACST },
|
||||
{ "AddHDMI_8000000", "AddHDMI", FIX_HDMI },
|
||||
{ "FixRegions_10000000", "FixRegions", FIX_REGIONS },
|
||||
{ "FixHeaders_20000000", "FixHeaders", FIX_HEADERS },
|
||||
{ "FixHeaders_20000000", "FixHeaders", FIX_HEADERS_DEPRECATED },
|
||||
{ NULL, "FixMutex", FIX_MUTEX }
|
||||
};
|
||||
|
||||
@ -99,9 +103,31 @@ public:
|
||||
ACPI_DSDT_Fixe_Array[idx].reset();
|
||||
}
|
||||
};
|
||||
// virtual bool parseFromXmlLite(XmlLiteParser* xmlLiteParser, const XString8& xmlPath, bool generateErrors) override;
|
||||
|
||||
virtual XmlAbstractType& parseValueFromXmlLite(XmlLiteParser* xmlLiteParser, const XString8& xmlPath, bool generateErrors, const XmlParserPosition &keyPos, const char *keyValue, size_t keyValueLength, bool* keyFound) override;
|
||||
|
||||
virtual bool validate(XmlLiteParser* xmlLiteParser, const XString8& xmlPath, const XmlParserPosition& keyPos, bool generateErrors) override {
|
||||
if ( !super::validate(xmlLiteParser, xmlPath, keyPos, generateErrors) ) return false;
|
||||
if ( !isDefined() ) return true;
|
||||
// if ( LString8(ACPI_DSDT_Fixe_Array[29].getNewName()) != "FixHeaders_20000000"_XS8 ) {
|
||||
// log_technical_bug("ACPI_DSDT_Fixe_Array[29].getNewName() != \"FixHeaders_20000000\"");
|
||||
// return true; // Bug in ACPI_DSDT_Fixe_Array. We don't want to reset all the values, so return true.
|
||||
// }
|
||||
// if ( ACPI_DSDT_Fixe_Array[29].isDefined() ) {
|
||||
// xmlLiteParser->addWarning(generateErrors, S8Printf("FixHeaders is ACPI/DSDT in deprecated. Move it to ACPI."));
|
||||
// return true; // return true because we handle this value anyway.
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
const ACPI_DSDT_Fix& getFixHeaders() const {
|
||||
// FixHeaders is bit 29, but that's a coincidence with the index of the array. ACPI_DSDT_Fixe_Array[FIX_HEADERS_DEPRECATED] would be wrong.
|
||||
if ( LString8(ACPI_DSDT_Fixe_Array[29].getNewName()) != "FixHeaders_20000000"_XS8 ) {
|
||||
log_technical_bug("ACPI_DSDT_Fixe_Array[29].getNewName() != \"FixHeaders_20000000\"");
|
||||
}
|
||||
return ACPI_DSDT_Fixe_Array[29];
|
||||
}
|
||||
|
||||
uint32_t dgetFixBiosDsdt() const {
|
||||
uint32_t FixDsdt = 0;
|
||||
for (size_t Index = 0; Index < sizeof(ACPI_DSDT_Fixe_Array)/sizeof(ACPI_DSDT_Fixe_Array[0]); Index++) {
|
||||
@ -109,6 +135,9 @@ public:
|
||||
}
|
||||
return FixDsdt;
|
||||
}
|
||||
bool dgetFixHeaders() const {
|
||||
return getFixHeaders().dgetEnabled();
|
||||
}
|
||||
};
|
||||
|
||||
class ACPI_DSDT_Patch_Class : public XmlDict
|
||||
|
@ -43,7 +43,7 @@ private:
|
||||
bool m_isDefined;
|
||||
|
||||
public:
|
||||
XmlAbstractType() : m_isDefined(false) {};
|
||||
constexpr XmlAbstractType() : m_isDefined(false) {};
|
||||
virtual ~XmlAbstractType() {};
|
||||
|
||||
virtual const char* getDescription() = 0;
|
||||
@ -98,8 +98,8 @@ public:
|
||||
protected:
|
||||
bool booll = false;
|
||||
public:
|
||||
XmlStrictBool() : super() {};
|
||||
XmlStrictBool(bool b) : booll(b) { /*if (b) b = 1;*/ }
|
||||
constexpr XmlStrictBool() : super() {};
|
||||
constexpr XmlStrictBool(bool b) : booll(b) { /*if (b) b = 1;*/ }
|
||||
|
||||
virtual void reset() override { super::reset(); booll = 0; };
|
||||
virtual const char* getDescription() override { return "boolean"; };
|
||||
|
@ -506,8 +506,8 @@ int documentation_test1()
|
||||
class MyDictClass : public XmlDict
|
||||
{
|
||||
public:
|
||||
XmlBool aBool;
|
||||
XmlInt32 anInt32;
|
||||
XmlBool aBool {};
|
||||
XmlInt32 anInt32 {};
|
||||
|
||||
XmlDictField m_fields[2] = {
|
||||
{"KeyNameForBool", aBool},
|
||||
@ -548,8 +548,8 @@ int documentation_test2()
|
||||
class MyInsideDictClass : public XmlDict
|
||||
{
|
||||
public:
|
||||
XmlBool aBool;
|
||||
XmlInt32 anInt32;
|
||||
XmlBool aBool {};
|
||||
XmlInt32 anInt32 {};
|
||||
|
||||
XmlDictField m_fields[2] = {
|
||||
{"KeyNameForBool", aBool},
|
||||
@ -561,7 +561,7 @@ int documentation_test2()
|
||||
class MyTopLevelDictClass : public ConfigPlistAbstractClass
|
||||
{
|
||||
public:
|
||||
MyInsideDictClass inside1;
|
||||
MyInsideDictClass inside1 {};
|
||||
|
||||
XmlDictField m_fields[1] = {
|
||||
{"KeyNameForInsideDict", inside1},
|
||||
@ -600,8 +600,8 @@ int documentation_test3()
|
||||
class MyPlist : public ConfigPlistAbstractClass
|
||||
{
|
||||
public:
|
||||
XmlBool aBool;
|
||||
XmlInt32 anInt32;
|
||||
XmlBool aBool {};
|
||||
XmlInt32 anInt32 {};
|
||||
class CountClass : public XmlInt64
|
||||
{
|
||||
using super = XmlInt64;
|
||||
@ -678,9 +678,9 @@ int documentation_test4()
|
||||
{
|
||||
using super = XmlDict;
|
||||
public:
|
||||
MyXmlType type; // this is a subclass of XmlUInt8 that check that type is 1 or 2
|
||||
MyXmlSubType subType; // this is a subclass of XmlUInt8 that check that subtype is 11 or 12
|
||||
XmlString8 name; // as many other field that there is in this dict
|
||||
MyXmlType type {}; // this is a subclass of XmlUInt8 that check that type is 1 or 2
|
||||
MyXmlSubType subType {}; // this is a subclass of XmlUInt8 that check that subtype is 11 or 12
|
||||
XmlString8 name {}; // as many other field that there is in this dict
|
||||
|
||||
XmlDictField m_fields[2] = {
|
||||
{"Type", type},
|
||||
@ -737,9 +737,9 @@ int documentation_test5()
|
||||
{
|
||||
using super = XmlDict;
|
||||
public:
|
||||
XmlUInt8 type; // no validation except that the value is an unsigned 8 bits int
|
||||
XmlUInt8 subType; // no validation except that the value is an unsigned 8 bits int
|
||||
XmlString8 name; // as many other field that there is in this dict
|
||||
XmlUInt8 type {}; // no validation except that the value is an unsigned 8 bits int
|
||||
XmlUInt8 subType {}; // no validation except that the value is an unsigned 8 bits int
|
||||
XmlString8 name {}; // as many other field that there is in this dict
|
||||
|
||||
XmlDictField m_fields[2] = {
|
||||
{"Type", type},
|
||||
@ -806,7 +806,7 @@ int documentation_test6()
|
||||
class MyDictClass : public ConfigPlistAbstractClass
|
||||
{
|
||||
public:
|
||||
XmlArray<XmlBool> aBoolArray;
|
||||
XmlArray<XmlBool> aBoolArray {};
|
||||
|
||||
XmlDictField m_fields[1] = {
|
||||
{"KeyNameForBoolArray", aBoolArray},
|
||||
@ -844,7 +844,7 @@ int documentation_test7()
|
||||
class MyDictClass : public ConfigPlistAbstractClass
|
||||
{
|
||||
public:
|
||||
XmlRepeatingDict<XmlAddKey<XmlKey, XmlInt32>> keyIntPairs;
|
||||
XmlRepeatingDict<XmlAddKey<XmlKey, XmlInt32>> keyIntPairs {};
|
||||
|
||||
XmlDictField m_fields[1] = {
|
||||
{"KeyNameForKeyIntPairs", keyIntPairs},
|
||||
|
@ -45,7 +45,7 @@
|
||||
#define FIX_ACST bit(26)
|
||||
#define FIX_HDMI bit(27)
|
||||
#define FIX_REGIONS bit(28)
|
||||
#define FIX_HEADERS bit(29)
|
||||
#define FIX_HEADERS_DEPRECATED bit(29) // deprecated !!
|
||||
#define FIX_MUTEX bit(30)
|
||||
|
||||
|
||||
|
@ -448,6 +448,8 @@ void FillInputs(BOOLEAN New)
|
||||
InputItems[InputItemsCount++].SValue.SWPrintf("%04hhu", gSettings.Quirks.OcBooterQuirks.ProvideMaxSlide);
|
||||
InputItems[InputItemsCount].ItemType = BoolValue; //123
|
||||
InputItems[InputItemsCount++].BValue = gSettings.GUI.ProvideConsoleGop;
|
||||
InputItems[InputItemsCount].ItemType = BoolValue; //124
|
||||
InputItems[InputItemsCount++].BValue = gSettings.ACPI.FixHeaders;
|
||||
|
||||
|
||||
|
||||
@ -1067,6 +1069,11 @@ void ApplyInputs(void)
|
||||
gSettings.GUI.ProvideConsoleGop = InputItems[i].BValue;
|
||||
DBG("applied ConsoleGopEnable=%s\n", gSettings.GUI.ProvideConsoleGop ? "Y" : "N" );
|
||||
}
|
||||
i++; //124
|
||||
if (InputItems[i].Valid) {
|
||||
gSettings.ACPI.FixHeaders = InputItems[i].BValue;
|
||||
DBG("applied gSettings.ACPI.FixHeaders=%s\n", gSettings.ACPI.FixHeaders ? "Y" : "N" );
|
||||
}
|
||||
|
||||
|
||||
if (NeedSave) {
|
||||
@ -2064,7 +2071,7 @@ REFIT_ABSTRACT_MENU_ENTRY* SubMenuDsdtFix()
|
||||
SubScreen->AddMenuCheck("Rename ACST", FIX_ACST, 67);
|
||||
SubScreen->AddMenuCheck("Add HDMI", FIX_HDMI, 67);
|
||||
SubScreen->AddMenuCheck("Fix Regions", FIX_REGIONS, 67);
|
||||
SubScreen->AddMenuCheck("Fix Headers", FIX_HEADERS, 67);
|
||||
// SubScreen->AddMenuCheck("Fix Headers", FIX_HEADERS_DEPRECATED, 67);
|
||||
SubScreen->AddMenuCheck("Fix Mutex", FIX_MUTEX, 67);
|
||||
|
||||
SubScreen->AddMenuEntry(&MenuEntryReturn, false);
|
||||
@ -2146,6 +2153,7 @@ REFIT_ABSTRACT_MENU_ENTRY* SubMenuACPI()
|
||||
SubScreen->AddMenuEntry(SubMenuDsdtFix(), true);
|
||||
SubScreen->AddMenuEntry(SubMenuDSDTPatches(), true);
|
||||
SubScreen->AddMenuItemInput(49, "Fix MCFG", FALSE);
|
||||
SubScreen->AddMenuItemInput(124, "Fix Headers", gSettings.ACPI.FixHeaders);
|
||||
|
||||
SubScreen->AddMenuEntry(&MenuEntryReturn, false);
|
||||
return Entry;
|
||||
|
Loading…
Reference in New Issue
Block a user