-
Notifications
You must be signed in to change notification settings - Fork 46
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
SerialInit does not work for all serial ports #1954
SerialInit does not work for all serial ports #1954
Comments
I can get serial output from EFI to my PCIe serial port by modifying console input and output device paths (I don't think console output is the same as the output that First, I load the serial driver using Driver####. Loading the driver this way loads it before the Startup Manager (when you would hold the option key to view boot options from the Apple Boot Picker).
( Then you get additional options that can be used as console input and output device paths. The list of options are stored in ConInDev, ConOutDev, and ErrOutDev:
The list for each is like this (one set for each serial port):
For ConOut and ErrOut there's also the display device path included in each list:
You can find the ioreg path that the EFI path is pointing to like this:
The result indicates my graphics card:
So I changed ConIn, ConOut, and ErrOut to my serial port using VT100 terminal emulation since that's one of the options available in Serial.app which is what I'm using to view the output:
With these settings, I can boot into RefindPlus, go into the EFI Shell, and see output go to my serial port. Since it's using VT100 terminal emulation, I also get the 8 colors and two intensity levels for the text just like what you see in the EFI Shell. I don't know if there's a mode that does the text colors and utf8? But for some reason, my ConOut ended up pointing to two devices:
so the output is being sent to the screen and to the serial port. The problem is that the screen is stuck at 24 rows which causes the cursor to jump to the 24th row in the serial terminal (such as after an With OpenCore, I get some serial output until OpenCore outputs "Install Console control" then I don't see serial output until the kernel's serial kprintf begins. Maybe there are some config.plist options I can tweak here to affect the console in OpenCore? If I try to enter OpenShell.efi from OpenCore with these serial port settings, then I get a halt error. |
A couple things I noticed:
|
By changing |
If we need to update the PCD values, it can be done as shown in acidanthera/OpenCorePkg@011ae92. Does this help? |
It appears PcdSerialPciDeviceInfo is a kind of PCI device path that can point to an arbitrary serial port PCIe device, so maybe it's sufficient for the SerialInit issue. Shouldn't the PCD values be set before calling But what exactly is a PCD value? Where are PCD values stored? Do they work on EFI 1.1 Macs like my MacPro3,1? If it requires recompiling, then it's not useful. Is there a way to load PCD values from nvram or config? Can this loading of PCD values be performed by OpenCore or a driver that loads before OpenCore? |
Yes, we can just read the values from config, which can be done within OcMainLib. |
UPDATE: I created a sample of PCD value overriding at acidanthera/OpenCorePkg@36b5829. If this will be what we expect, then we can start working on this. Or did I miss anything? |
Don't I think the equivelant Are the nested array and dict necessary? It could be simplified:
Is |
I am not sure to be honest. I was just trying to implement what you proposed. Actually, isn't it always 4-byte long as per https://github.com/acidanthera/audk/blob/bb1bba3d776733c41dbfa2d1dc0fe234819a79f2/MdeModulePkg/MdeModulePkg.dec#L1386?
@vit9696 introduced this idea at first. I do not know whether we should add multiple devices support (i.e. via array).
I don’t know either. In my opinion, better to rename it to |
Does the stuff to be implemented require the DevicePath? Only if you were going to do something about the device properties issue (which I don't require since I'm using the kext method to disable the used serial port). Actually, isn't it always 4-byte long as per https://github.com/acidanthera/audk/blob/bb1bba3d776733c41dbfa2d1dc0fe234819a79f2/MdeModulePkg/MdeModulePkg.dec#L1386? I think the Pcd's with type But it seems to me that since Pcd's are not named with an ASCII string (are they? I don't know enough about Pcd's) then OpenCore will only be able to change Pcd's that it knows about (it cannot change a Pcd given its name as an ASCII string unless it knows the name). In that case, you might as well create a structure for each Pcd that makes it easiest to read. In the case of PcdSerialPciDeviceInfo, a format like this might be best:
Do you mean multiple Serial devices? Then it would be more like this:
I think so, If |
Fixed PCD variables are just global variables inside OpenCore, which we can update as long as we know how. When the complete list of the variables we need to change is figured out, they should be put to
To be able to write to the variables of type data (e.g. I do not believe we need to support multiple device paths at once, and
@joevt, please add what you think is also necessary. Given the amount of entries to become configurable, |
Thanks @vit9696! Shall we create a new structure for config.plist? Afterwards, I can work on that. |
I think so. |
That should be enough for my PCIe Serial port path. Maybe double that for safety (41 bytes) in case someone wants to try something weird like serial port from Thunderbolt. Or make it arbitrary length and allocate memory from the pool? It's a singleton so it doesn't need to be cleaned up afterward to avoid memory leaks assuming OpenCore is opened multiple times during the same boot.
That should be fine. It's easy enough to construct by hand using
To be safe, better just add all of the PcdSerial* pcd's that you listed. Adding 12 will take similar effort to adding 6 I believe. You didn't list |
You cannot allocate from pool there, as you need to update a global array of fixed size.
Fair.
Yes, it is not used, so I do not see a reason to add it. |
One question - shall we always override all 12 keys? I do not see any good way not to override if we will. As for config structure, I would agree with a new field at Misc. i.e. Misc -> Serial -> pcd keys to be overridden like on #1954 (comment). |
I think it is ok to fill all the fields with known values via |
acidanthera/OpenCorePkg@c3b41c9 |
I think we should introduce a kernel quirk to perform such a patch, based on Misc → Serial data. |
@joevt Would you please explain how this is calculated based on Serial data? EDIT - I created the quirk hierarchy at acidanthera/OpenCorePkg#331. You can work on the |
I've added my notes for the suggested quirk in acidanthera/OpenCorePkg#331 |
The main issue
SerialInit relies on BaseSerialPortLib16550 which relies on PCDs.
It is not clear from the documentation how it can be used with arbitrary serial ports.
For example, I have a PCIe serial port card which contains two serial ports. Can OpenCore output log messages to my serial ports or do I need to change some build settings? Maybe it can work since my serial ports are based on 16x50 which BaseSerialPortLib16550 should be able to work with, but what about other serial port options? Ideally, this feature should work without having to rebuild OpenCore.
Possible solution
Maybe OpenCore should have options to select a device that has SerialIo protocol (using a device path in case there are many serial ports)? The serial port functions in OpenCore can be wrapped to support either the SerialIo Protocol or the SerialPortLib. Does the SerialPortLib work beyond ExitBootServices? It could be possible - all you need to use the 16x50 serial port is the
in
andout
x86 instructions to access static I/O addresses. If SerialPortLib and SerialIo protocol have different usage or behaviour after ExitBootServices then that should be taken into account.Using PCIe serial port for serial kprintf
I have a kernel patch to use a PCIe serial port for serial kprintf in macOS. Click the spoiler to see:
PCIe serial patch for xnu kernel
For this to work, I need to enable I/O addresses for the PCIe device. This can be done in the UEFI Shell:
mm 180000004 1 -w 1 -pcie
(my PCIe serial port is at 18:0:0)but a better way is to load a UEFI driver. SerialDxe.efi is one possibility, but that uses SerialPortLib so it takes more work to build. PciSioSerialDxe.efi is easy to build and seems to work directly with 16x50 based serial ports, at least for enabling I/O addresses but I haven't used it to transmit text over serial port while still in UEFI. Is there a way to redirect console input and output in the UEFI Shell? I understand there are some nvram variables for this but can they work when the serial driver loading is deferred? I think it would be useful for OpenShell to have a command to redirect console input/output and for OpenCore to be able to do the same.
For serial kprintf, you need some boot-args:
debug=0x108 -v serial=3 msgbuf=1048576 serialbaud=115200
I'm not sure what msgbuf does or what the default value is. It doesn't appear to be a boot-arg in the latest xnu. It is mentioned in the OpenCore documentation.
It may be that when macOS attaches its Apple16X50PCI0 driver, it will disable kprintf. kprintf will start working again if I launch Serial.app to open the serial port. To stop Apple16X50PCI0 from attaching, I tried a DeviceProperties patch to alter the
class-code
:DeviceProperties -> Add
DeviceProperties -> Delete
The PCIe device has two functions (function 0 and function 2), one for each serial port. I only want to disable matching for the first serial port (that I've reserved for serial kprintf) at function 0 as indicated by the second 0x0 in the last Pci node of the device path. However, the patch gets applied to both functions. Similarly, if I change that 0x0 to 0x2 like this:
PciRoot(0x0)/Pci(0x9,0x0)/Pci(0x0,0x0)/Pci(0x1,0x0)/Pci(0x0,0x2)
then the patch is not applied to either function. The OpenCore documentation regarding DeviceProperties doesn't seem to have an explanation for this (but it does say devices that don't exist in ACPI may have issues). It seems to me that OpenCore should have its own method of applying DeviceProperties, perhaps using Lilu, maybe by patching IOService->registerService so that the properties are applied before driver matching occurs. Currently, the resulting properties in the I/O Registry can only be Data. OpenCore's device properties patch could allow arbitrary types such as Number, String, Dict, Array.Instead of using DeviceProperties to stop drivers from attaching to the serial port that is reserved for serial kprintf, I used a codeless kext injected by OpenCore to attach to the reserved serial port. I used IOPropertyMatch to match only function 0 (which has IOChildIndex 1). With this method, function 0 is no longer usable in macOS (it's only used for serial kprintf) and I can still use the other serial port (function 2).
PCIeSerialDisable.kext/Contents/Info.plist
Kernel -> Add
I haven't tried this from Thunderbolt. It should work if the I/O addresses never change. This requires that the Thunderbolt devices exist in UEFI before macOS boots and that you don't do any hot plugging of Thunderbolt devices connected to the same port or bus that the PCIe card is connected to.
The text was updated successfully, but these errors were encountered: