Closed Thireus closed 4 years ago
This is not right. Read-only partitions are supported, OpenCore will boot fine when it cannot create a log file silently avoiding log file creation. The error you pasted says that you have a mistake on your configuration caused by the HfsPlus.efi driver file not present on the filesystem.
Hi vit9696,
First of all, I just wanted to say thank you, I really appreciate your hard work.
Now, I can understand why your immediate reaction was to reject the issue when you saw it related to HfsPlus.efi missing, which appears to be a common mistake made by many novice users.
Rest assured that I have checked my configuration more than once.
My HfsPlus.efi file is present on my OpenCore EFI and is located there:
/Volumes/EFI/EFI/OC/Drivers/HfsPlus.efi
I can also confirm that my OpenCore EFI works very well when my drive is set to RW. I can confirm I am able to boot on macOS just fine. The issue only occurs when I set the SAME drive in RO mode.
The drive is an SD card which can easily be set to RO by a flip of the side switch. So this is the same setup, the same files, the same drive.
I also understand it is certainly not related to log files. I was just pointing out that in RW mode, there are files written by OpenCore and logs are some of them.
Please advise. Thank you.
Steps to reproduce the issue:
@Thireus I'm using a Kanguru FlashBlu 16GB usb drive which has a "true" read only switch once you've made the USB which is not host dependant as the card switch.
No issues so far in read-only and RW mode, with macOS, Linux, windows etc.
You should know that the operating system itself accepts to mount the SD card read-only, and this could be exploited easily since it's only a software limitation not a hardware switch which limits the maximum current/voltage to the flash storage for writing, since the necessary voltage required for writing is greater than the one requested for reading
This would be file system corruption or BIOS driver issues in this case. I.e. the file system on your SD card for some reason is not valid for the file system driver in your BIOS, and thus OpenCore does not see anything. I am afraid not much can be done about it, since it is an issue with the particular hardware on the BIOS side, but you could try reformatting your SD card.
You could try to use a USB card reader but that would instantly bypass the read-only card's switch making it RW
Thank you both for the tips. @vit9696 I think you just guessed it right, there is something going on with the BIOS and SD card FS.
I've just tired to boot OpenCore using VirtualBox. It works! Even with RO enabled on the SD card... So, nothing wrong with OpenCore then. I'll continue investigating the issue and post an update here once I found the culprit.
Update:
The following code is executed (cf. https://github.com/acidanthera/OpenCorePkg/blob/master/Library/OcStorageLib/OcStorageLib.c#L247):
Status = SafeFileOpen (
Context->StorageRoot,
&File,
(CHAR16 *) FilePath,
EFI_FILE_MODE_READ,
0
);
The Status value is "8" when attempting to access Drivers/HfsPlus.efi when I boot the SD Card as Read Only.
That seems to corresponds to the following (cf https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Uefi/UefiBaseType.h):
define EFI_WRITE_PROTECTED RETURN_WRITE_PROTECTED
This is what I've modified in the code:
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "THIREUS: EFI_ERROR %s: %d\n", FilePath, Status));
return NULL;
}
This is what OpenCore displays:
THIREUS: EFI_ERROR Drivers\HfsPlus.efi: 8
This seems very strange that RETURN_WRITE_PROTECTED is considered as an error, especially when EFI_FILE_MODE_READ is specified... Any idea why?
I'll patch the code to accept Status 8 as a non-EFI_ERROR and see how it goes.
This is a patch that works for my RO SD Card:
// Thireus patch
if (OpenMode == EFI_FILE_MODE_READ && Status == EFI_WRITE_PROTECTED){
Status = EFI_SUCCESS;
}
Patched inside https://github.com/acidanthera/OpenCorePkg/blob/master/Library/OcFileLib/OpenFile.c
Functions: SafeFileOpen(...) and OcOpenFileByDevicePath(...) before the return Status;
.
I can confirm I can finally boot successfully in RO mode with the above.
I'm not knowledgeable on EFI functioning. To me it seems that whichever lib is handling EFI Open operations it is not correctly interpreting the EFI_FILE_MODE_READ Openmode and triggers by mistake a RETURN_WRITE_PROTECTED EFI_ERROR when the accessed resource is read-only...
Is my BIOS manufacturer to blame? @vit9696, any idea?
According to the UEFI specification, page 510, EFI_WRITE_PROTECTED
can only be returned from EFI_FILE_PROTOCOL
Open
function when An attempt was made to create a file, or open a file for write when the media is write-protected.
. This an error condition and the file does not open in this case as the only condition for file open is EFI_SUCCESS
— The file was opened.
So yes, your BIOS is not behaving correctly and is violating the specification.
On the other side I do not believe it is possible for a valid firmware to return EFI_WRITE_PROTECTED
for EFI_FILE_MODE_READ
, so we could technically add a hack for your BIOS to treat file reads resulting in write protected as successful operations without affecting other systems.
If others do not mind, I suggest to change the code as shown below. OcOpenFileByDevicePath
does not need to be changed as it eventually uses SafeFileOpen
as well. This code snippet will need testing before merging AND it will need the comments clarifying what exact board, firmware (if known), CPU generation, SD card, and card reader this was reproduced on.
EFI_STATUS
SafeFileOpen (
IN EFI_FILE_PROTOCOL *Protocol,
OUT EFI_FILE_PROTOCOL **NewHandle,
IN CONST CHAR16 *FileName,
IN UINT64 OpenMode,
IN UINT64 Attributes
)
{
EFI_STATUS Status;
UINTN Length;
DEBUG_CODE_BEGIN ();
ASSERT (FileName != NULL);
ASSERT (NewHandle != NULL);
Length = StrLen (FileName);
if (Length > 0 && FileName[Length - 1] == L'\\') {
DEBUG ((DEBUG_INFO, "OCFS: Filename %s has trailing slash\n", FileName));
}
DEBUG_CODE_END ();
*NewHandle = NULL;
Status = Protocol->Open (
Protocol,
NewHandle,
(CHAR16 *) FileName,
OpenMode,
Attributes
);
if (Status == EFI_WRITE_PROTECTED
&& OpenMode == EFI_FILE_MODE_READ
&& Attributes == 0
&& *NewHandle != NULL) {
Status = EFI_SUCCESS;
}
return Status;
}
CC @Download-Fritz @Goldfish64
@vit9696 Maybe add a DEBUG_INFO so that if we ever run into a weird issue with this it's at least visible?
Won't risk the recursion; verbose at most.
Hi @vit9696, thank you for the explanation. I'll write to Asus and see if they can fix that in their next x299 BIOS release.
Unfortunately only patching SafeFileOpen
is not sufficient (I've tried).
When Kext plists are loaded (ie. Lilu.kext) the OcOpenFileByDevicePath
function is used instead. So that one also requires patching.
SafeFileOpen
:
EFI_STATUS
SafeFileOpen (
IN EFI_FILE_PROTOCOL *Protocol,
OUT EFI_FILE_PROTOCOL **NewHandle,
IN CONST CHAR16 *FileName,
IN UINT64 OpenMode,
IN UINT64 Attributes
)
{
EFI_STATUS Status;
UINTN Length;
DEBUG_CODE_BEGIN ();
ASSERT (FileName != NULL);
Length = StrLen (FileName);
if (Length > 0 && FileName[Length - 1] == L'\\') {
DEBUG ((DEBUG_INFO, "OCFS: Filename %s has trailing slash\n", FileName));
}
DEBUG_CODE_END ();
Status = Protocol->Open (
Protocol,
NewHandle,
(CHAR16 *) FileName,
OpenMode,
Attributes
);
if (Status == EFI_WRITE_PROTECTED
&& OpenMode == EFI_FILE_MODE_READ
&& Attributes == 0
&& *NewHandle != NULL) {
Status = EFI_SUCCESS;
}
return Status;
}
OcOpenFileByDevicePath
:
EFI_STATUS
EFIAPI
OcOpenFileByDevicePath (
IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
OUT EFI_FILE_PROTOCOL **File,
IN UINT64 OpenMode,
IN UINT64 Attributes
)
{
EFI_STATUS Status;
EFI_HANDLE FileSystemHandle;
ASSERT (File != NULL);
ASSERT (FilePath != NULL);
//
// Look up the filesystem.
//
Status = gBS->LocateDevicePath (
&gEfiSimpleFileSystemProtocolGuid,
FilePath,
&FileSystemHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = OcOpenFileByRemainingDevicePath (
FileSystemHandle,
*FilePath,
File,
OpenMode,
Attributes
);
if (Status == EFI_WRITE_PROTECTED
&& OpenMode == EFI_FILE_MODE_READ
&& Attributes == 0
&& *File != NULL) {
Status = EFI_SUCCESS;
}
return Status;
}
Recompiling OpenCore and all Kexts is necessary.
I can confirm that patching both SafeFileOpen
and OcOpenFileByDevicePath
is a requirement and works with the latest OpenCore commit: ba5eea2de4c347630441df71f933a01f8e9198fb.
But OcOpenFileByRemainingDevicePath calls SafeFileOpen, its implementation is right above. So it must be some other inner call that fails. Could you trace it? It is not correct to fix OcOpenFileByDevicePath, should be somewhere in its children.
Also, please be more descriptive about your board.
I believe it is OpenVolume (https://github.com/acidanthera/OpenCorePkg/blob/master/Library/OcFileLib/OpenFile.c#L99) that causes issues. Could you check it? If so, we should introduce SafeOpenVolume and fix it in more places.
@vit9696, could be OpenVolume indeed. I will try trace it as soon as I have some free time and I'll let you know exactly where it gets the EFI_WRITE_PROTECTED Status from.
BIOS: ROG RAMPAGE VI EXTREME BIOS 3105 BOARD: ROG RAMPAGE VI EXTREME LINK: https://rog.asus.com/us/motherboards/rog-rampage/rog-rampage-vi-extreme-model/helpdesk_bios/
@vit9696, my mistake. I can confirm only patching SafeFileOpen
is sufficient!
Most likely I had not recompiled the kexts properly during my previous tests.
Also, I just opened a ticket with Asus. Hopefully they'll be able to acknowledge that they don't follow the specs and patch that in the next BIOS release.
Bro, I am using acer swift3 sf314-55g laptop. I am getting error Driver HfsPlus.efi at 0 cannot be found!. I will attach my config.plist to it. sampath config.zip
Currently OpenCore requires write access to the EFI partition in order to function. Several files are written to that partition (not only log files) when OpenCore loads. If write access isn't provided, OpenCore will not load and will display:
Any chance to support read-only EFI partitions in the future?
Some users might find it helpful to support read-only bootloaders which helps prevent bootloader tampering.