New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OC: Option for NVRAM persistence to enable boot-arg modification and SIP disable #575
Comments
Hi, Firstly, regarding the concept.
Secondly, about the expected workflow.
Given the above, I do not see an issue or the need to change anything. The logic looks perfectly natural to me. |
Let me do some more tests and I will get back to you on the override behaviour I observed. Regarding "We do not believe any machine should need any boot arguments to work", is there a device injection option for |
That's a good point, should really implement them as IGPU properties. Could you submit a bugreport please?
I believe macOS firstly deletes variables. Or my firmware is non-conformant, as we tested the behaviour above and it worked. We could consider some routes to fix this in case it causes problems. One of them is to make |
@vit9696 This is a tough question because in the end it's a bug in Apple's nvram utility if it really does not delete the variables first. If you "fix" it in FwRuntimeServices, it will explicitly violate the spec. On the other hand, I don't see a good point for the specified behaviour either except as some sort of request sanitizing, imo wait for what @osy86 has to report later. |
This is what I've tested First boot:
After rebooting:
I've also reversed |
Thanks. In this case I do not mind ignoring the spec and incorporating the following change in SetVariable wrapper of FwRuntimeServices.efi.
|
Implemented in
|
@osy86 can we close this now? |
Sorry, will test tomorrow. Just got back tonight. |
On latest release of OC and AppleSupport:
|
Are you positive this is not caused by System Integrity Protection or alike? |
This is the same computer/configuration as #575 (comment) and also SIP shouldn't affect boot-args variable right |
From what I remember SIP does affect boot-args. You cannot e.g. add -s argument at the very least, and only a few boot arguments from a white list were allowed in older macOS versions. I do not know how it is now, but it should be like just -v or such. That is why NVIDIA was forced to stop using a boot argument for their web drivers for instance. |
So creating a new variable still works. Setting a variable already marked NV (I used "prev-lang:kbd") still works. It seems only previously volatile variables now trigger that error instead of silently failing to change attribute. That's strange to me. Looking at the edit, https://github.com/acidanthera/AppleSupportPkg/blob/master/Platform/FwRuntimeServices/UefiRuntimeServices.c#L981 this implies that previously |
@vit9696 can you explain the reasoning for this snippet? https://github.com/acidanthera/AppleSupportPkg/blob/master/Platform/FwRuntimeServices/UefiRuntimeServices.c#L994-L1000 |
Variables in Apple Boot namespace, i.e. the ones accessed by nvram tool without the GUID prefix are not written immediately, but actually are cached and written at power off. Well, at least were :D. What you see here looks like a SIP check. |
As for the reasoning for the snippet, it removes the already present variable, you have to pass NULL value and size for that as per UEFI spec, and then sets a new one with different arguments. It is indeed the case that I did not check the error code for the first SetVariable, but most likely it is only good for debug reasons. |
You're right, I must have tested with SIP disabled before. Now I get the same behaviour as before with SIP disabled (setting boot-args does not persist). Since the changes aren't committed until power off, perhaps the original issue isn't what I thought with the SetVariable but something is causing the change to not be written to NV storage. |
Perhaps your BIOS deviates from the specification and silently fails instead of returning invalid parameter? Could you try playing with the error condition maybe… |
Yeah, I'll debug it more this weekend. |
I'm testing with a new variable
I replaced the code so it will always run: Status = mStoredGetVariable (
VariableName,
VendorGuid,
&CurrAttributes,
&CurrSize,
NULL
);
mStoredSetVariable (
VariableName,
VendorGuid,
CurrAttributes,
0,
NULL
);
Status = mStoredSetVariable (
VariableName,
VendorGuid,
Attributes,
DataSize,
Data
); Boot into OSX with SIP disabled. |
Does the same happen during boot, i.e. if you call those functions with a hardcoded variable before OS start? What status do the first two calls return each (you could log to another var)? |
Should this create a variable named "teststatus"? If so, it's not working. |
Fun. I think it does not matter when calling the stored func, but is DisableVariableWrite on? Is it an ASUS board? If so, which model? |
Okay this is bizarre. I went ahead and deleted the new code and changed the set to Status = mStoredSetVariable (
VariableName,
VendorGuid,
Attributes | EFI_VARIABLE_NON_VOLATILE,
DataSize,
Data
); Explicating adding |
@osy86 could you please elaborate the test you perform? It is a bit hard to judge from the contents. |
Yes, talking about accidental exploitation, when the OS is not compromised and did valid stuff, but our code tried that bruteforce, and bypassed authenticated variables for instance. |
I don't think it provides significant protection, but I won't repel it till somebody runs into variable size issues. |
Test code if (Status != EFI_BUFFER_TOO_SMALL) {
Status = gRT->SetVariable (
UnicodeVariableName,
VariableGuid,
OPEN_CORE_NVRAM_ATTR,
VariableSize,
VariableData
);
DEBUG ((
EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
"OC: Setting NVRAM %g:%a - %r\n",
VariableGuid,
AsciiVariableName,
Status
));
UINTN CurrSize;
UINT32 CurrAttributes;
char tmp[1024];
CurrAttributes = 0;
CurrSize = 0;
Status = gRT->GetVariable (
UnicodeVariableName,
VariableGuid,
&CurrAttributes,
&CurrSize,
NULL
);
DEBUG ((
EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
"OC: Readback NVRAM %g:%a, attributes:%d, size:%d - %r\n",
VariableGuid,
AsciiVariableName,
CurrAttributes,
CurrSize,
Status
));
CurrAttributes = 0;
CurrSize = 512;
Status = gRT->GetVariable (
UnicodeVariableName,
VariableGuid,
&CurrAttributes,
&CurrSize,
tmp
);
DEBUG ((
EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
"OC: Readback NVRAM %g:%a, attributes:%d, size:%d - %r\n",
VariableGuid,
AsciiVariableName,
CurrAttributes,
CurrSize,
Status
));
} Result
Now, I know it's unlikely for vars (such as boot-args) to be > 512 bytes. But that's not impossible, and in this case we regress to the old behaviour if the length is > an arbitrary number. If this is going to be the case, it would be good to have this behaviour documented somewhere just in case somebody runs into it. |
Yes, sure, I have just updated the docs to include this. This is fine to us, as basically this behaviour is rare, and most boards just allow writing non-volatile over volatile. Just a note, it sounds like a good idea to write to Intel and request them fix this. |
Okay so this is weird. I tried the latest FwRuntimeServices and it still doesn't work. So I logged the status codes and https://github.com/acidanthera/AppleSupportPkg/blob/master/Platform/FwRuntimeServices/UefiRuntimeServices.c#L1018 still returns |
Ergh, so you did not test it in runtime? Geh, now I do not like it. Could you please test further? In my opinion, the most likely case is that your firmware does not support creating non-volatile variables with the same name as volatile in runtime (only). |
Sorry, I was testing the 512 buffer first. I am going to add a Stall and try again.
But my code above did work for creating such variable. The only difference is that I have a bunch of print statements in between. EDIT: adding a delay didn't work. The delete (https://github.com/acidanthera/AppleSupportPkg/blob/master/Platform/FwRuntimeServices/UefiRuntimeServices.c#L1011) returns |
Ugh, okay this is again documented in UEFI specs
So if it wasn't set with |
Ok, we agreed to create a new option to make |
@osy86 I believe the issue is fully resolved in master. Sorry for taking so long. Please report whether it works fine now. |
Just did a test, the new option
is this due to broken nvram? |
yes. |
thanks, off topic, it would be wonderful if motherboards like B360M get hardware nvram, sometimes macOS panic or suddenly rebooted during daily usage (like yesterday it rebooted with no reason after 10 days uptime), there is barely no report to see what was the cause of the panic/reboot. |
It would be wonderful if people that need it go and do it. |
@vit9696 I can confirm it works. Thanks for the help! |
It doesn't work for Asus Sage C621 systems. Doesn't work for mine. And, no, a Asus X299 system is NOT a Z390..... |
Having same problem with ASUS x99 Deluxe. Real and Emulated NVRAM did not work. While everything fine with creating nvram.plist in EFI root with proper content, OC didn't get it on the boot. I.e altering boot-args with -uia_exclude_ss while configuring USB with USBMap fails after reboot. Emulating NVRAM like in manual: https://khronokernel-2.gitbook.io/opencore-vanilla-desktop-guide/post-install/nvram |
Sorry to chime in. I get
Only with this variable. And I've been reading here that you have a limit for the variables. In this case. The Find My Mac Token is really long (1422 bytes in my case). And I get the error either setting it up on the config.plist (via NVRAM > ADD parameters) or just on the Legacy nvram I have (nvram.plist). Can you give me a hand? I know. It's not that important. Actually I have a desktop system and FMM is not that useful, but eventually I'd like to get it working. |
It is your firmware NVRAM implementation that does not allow such long variables I am afraid. Not much to do here. |
I don't have hardware NVRAM. My system is old (P55 Motherboard) with legacy BIOS. I use emulated NVRAM. |
Well, that means the emulated NVRAM driver has such limitation. In this case it might be possible to increase the variable size by reconfiguring the driver. |
Can you guide me how to do that? Or can you increase the limitation for a future commit of OC? Like I said, the priority is way too low, so don't stress for that. Also thanks in advance. I'm very grateful for OpenCore. It's amazing! OT: I couldn't install windows in UEFI mode through OpenCore. I can format a hard drive and it creates all the partitions is UEFI mode (recovery, MSR, System and the actual NTFS) but after selecting it, it won't install. It says that the partition could'n be located. Do you know someone can help me? |
As for increasing variable size in our version of legacy installation please file a separate issue, but it is indeed unlikely we will look into it soon, sorry. As for installing Windows in UEFI mode, please be more specific. I am pretty sure it works on legacy installations, as @roddy20 has no issues with it. |
Here's the error: The windows installer can format the hard disk and create the proper partitions (I have OpenCore installed on another disk). But, when I select the partition, I get the above message and can't continue. Note that the created partitions are the ones created on an actual UEFI system. On legacy, windows creates System Reserved and the primary partition. Maybe @roddy20 can help me? |
In the current implementation, we can add UEFI variables using the
Add
key underNVRAM
. The wayOcSetNvramVariable
works is that it attempts to read the variable. If it's not found, then it will add it with the flagsEFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS
.Block
can be used to delete the variable first in order to always force theAdd
value instead.I propose a third option. Either a new key
Persist
that operates likeAdd
but creates the variable withEFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS
. Or a new optionPersistAdd
with a boolean value that will maskEFI_VARIABLE_NON_VOLATILE
forAdd
variables.Why is this useful? Consider the following use case: We need some base set of
boot-args
to boot up OSX. So we add them withAdd
. However, in the process of development/testing unrelated stuff, we wish to modifyboot-args
by appending some new string. Usingsudo nvram boot-args="new value"
fails because OSX will try to use the attributeEFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS
and it fails because in the EFI specs:Okay, so what if we just don't put
boot-args
into the config.plist. Instead we just setsudo nvram boot-args="some value"
initially. That works, except if we require certainboot-args
to boot, then forgetting to append them will make the system unbootable (even more painful if the vault is used). So ideally, we can use OC's "erase nvram" option to wipe all the variables and then reset them with a clean default.A second use case:
csr-active-config
is used for SIP. OSX does the checks to make surecsr-active-config
is only modified in recovery OS. However, setting it in recovery OS still doesn't work if there is already anAdd
entry. But if we do not includecsr-active-config
in bothAdd
then using OC's "erase nvram" option will always enable SIP.An option to allow the NVRAM options in config.plist to act as a signed/verified golden default configuration but still allow modification to NVRAM through normal OSX techniques would be useful.
The text was updated successfully, but these errors were encountered: