This repository contains a solution for the PLDM communication between the HOST (UEFI firmware) and BMC, with both implemented via open-source components:
- The HOST (UEFI firmware) part is based one the
edk2
andedk2-platforms
code, - The BMC part is based on the openbmc distribution.
The PLDM communication is provided via MCTP over KCS transport.
The current edk2-platfroms
repository has a ManagebilityPkg that can be used to add support for the PLDM communication based on the MCTP over KCS transport.
The modules in the ManagebilityPkg
can be used for different scenarios, so we have to configure them in the way that is needed for us:
- PLDM based on MCTP
- MCTP based on KCS
This can be done with the following configuration in the DSC
file:
[Components]
ManageabilityPkg/Universal/PldmProtocol/Dxe/PldmProtocolDxe.inf {
<LibraryClasses>
ManageabilityTransportLib|ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/DxeManageabilityTransportMctp.inf
}
ManageabilityPkg/Universal/MctpProtocol/Dxe/MctpProtocolDxe.inf {
<LibraryClasses>
ManageabilityTransportLib|ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe/DxeManageabilityTransportKcs.inf
}
For the successfull compilation we would also need to add a ManageabilityTransportHelperLib
library:
[LibraryClasses]
ManageabilityTransportHelperLib|ManageabilityPkg/Library/BaseManageabilityTransportHelperLib/BaseManageabilityTransportHelper.inf
And configure some PCDs:
[PcdsFixedAtBuild]
gManageabilityPkgTokenSpaceGuid.PcdMctpSourceEndpointId|9
gManageabilityPkgTokenSpaceGuid.PcdMctpDestinationEndpointId|8
gManageabilityPkgTokenSpaceGuid.PcdMctpKcsBaseAddress|0xca8
Couple of words about PCDs:
- The
PcdMctpSourceEndpointId
can be arbitrary (keep in mind that numbers 0-7 are reserved per specification), - The
PcdMctpDestinationEndpointId
is mapped to the defaultlibmctp
EID (https://github.com/openbmc/libmctp/blob/2a2a0f6fd83318cfc37f44a657c9490c6a58a03a/utils/mctp-demux-daemon.c#L43), - The
PcdMctpKcsBaseAddress
should be chosen based on your hardware settings and synced with the BMC settings. In this case I use0xca8
, later this value would be seen in the BMC configuration.
The MCTP communication on the BMC side is based on the kernel net mctp driver (info).
Currently there is no support for the MCTP over KCS binding (current bindings), but the repository contains patches for the kernel to add the necessary driver.
For the kernel-based MCTP stack it is necessary to add the following include to your machine configuration file:
require conf/distro/include/pldm.inc
Since currently there is no MCTP-over-KCS binding driver we need to add some patches to the kernel:
- 0001-ipmi-Move-KCS-headers-to-common-include-folder.patch
- 0002-ipmi-Create-header-with-KCS-interface-defines.patch
- 0003-mctp-Add-MCTP-over-KCS-transport-binding.patch
Add all of these patches to your OpenBMC distibution via a standard recipe override mechanics.
The pldm.inc
file that we've included earlier would add the kernel configuration options from the meta-phosphor/recipes-kernel/linux/mctp/mctp.cfg
file. So we need to add our driver to this Kconfig fragment:
diff --git a/meta-phosphor/recipes-kernel/linux/mctp/mctp.cfg b/meta-phosphor/recipes-kernel/linux/mctp/mctp.cfg
index 26f3c4157e..f73d55ffc9 100644
--- a/meta-phosphor/recipes-kernel/linux/mctp/mctp.cfg
+++ b/meta-phosphor/recipes-kernel/linux/mctp/mctp.cfg
@@ -1,3 +1,4 @@
CONFIG_MCTP=y
CONFIG_MCTP_SERIAL=y
CONFIG_MCTP_TRANSPORT_I2C=y
+CONFIG_MCTP_TRANSPORT_KCS=y
To the board DTS file we need to add a KCS channel with the enabled interrupt.
For example here is a configuration that I add to my DTS:
&kcs2 {
status = "okay";
aspeed,lpc-io-reg = <0xCA8 0xCA9>;
aspeed,lpc-interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
};
It is perfectly normal to have another KCS channel enabled in the system. For example on my board I also have kcs3 for the IPMI communication:
&kcs3 {
status = "okay";
aspeed,lpc-io-reg = <0xCA2>;
};
Keep in mind that kcs channels have some constraints about IO settings.
For example here are constraints for the IO port values (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/char/ipmi/kcs_bmc_aspeed.c?h=v6.5#n210):
/*
* We note D for Data, and C for Cmd/Status, default rules are
*
* 1. Only the D address is given:
* A. KCS1/KCS2 (D/C: X/X+4)
* D/C: CA0h/CA4h
* D/C: CA8h/CACh
* B. KCS3 (D/C: XX2/XX3h)
* D/C: CA2h/CA3h
* C. KCS4 (D/C: X/X+1)
* D/C: CA4h/CA5h
*
* 2. Both the D/C addresses are given:
* A. KCS1/KCS2/KCS4 (D/C: X/Y)
* D/C: CA0h/CA1h
* D/C: CA8h/CA9h
* D/C: CA4h/CA5h
* B. KCS3 (D/C: XX2/XX3h)
* D/C: CA2h/CA3h
There is also SIRQ constraint for the KCS1 channel that it can only use SIRQ1 or SIRQ12 (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/char/ipmi/kcs_bmc_aspeed.c?h=v6.5#n172)
Add the following package to your image:
pldm
Since mctp is a network device, before performing actual communication you have to open the interface and setup address and routing. Offcourse you can always do this manually by executing these commands on the running BMC system:
$ mctp addr add 8 dev mctpkcs2
$ mctp route add 9 via mctpkcs2
$ ifconfig mctpkcs2 up
But it would be better to write these commands in a systemd service that would be executed on every system start. You can find example of a recipe that adds such unit to the system in the recipes-support folder.
After all of the above steps are applied you need to build OpenBMC image and flash it to the target device.
Now you are ready to test MCTP communication from the HOST via the PldmMessage
UEFI application.
The repository contains a simple application for the UEFI shell (PldmMessage
), that utilizes EDKII_MCTP_PROTOCOL
to send GetPLDMTypes (0x04)
command
BMC handling for this command is located here.
Now when everything is in place, launch PldmMessage.efi
from the UEFI shell. Here is the expected output:
FS0:\> PldmMessage.efi
MCTP protocol version 256
PldmRequestBuffer[0]=0x95
PldmRequestBuffer[1]=0x00
PldmRequestBuffer[2]=0x04
PldmResponse[0]=0x1D
PldmResponse[1]=0x00
PldmResponse[2]=0x00
PldmResponse[3]=0x00
PldmResponse[4]=0x00
PldmResponse[5]=0x00
PldmResponse[6]=0x00
PldmResponse[7]=0x00
The UEFI
and mctpkcs
code are currently under development, so if you've encountered a situation with a broken KCS state machine, you can always reboot MCTP network interface on the BMC side with the following commands:
$ ifconfig mctpkcs2 down
$ ifconfig mctpkcs2 up