<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Consolas, Courier, monospace; font-size: 12pt; color: rgb(0, 0, 0);">
Yikes - that's embarrassing. Thanks for the fix.</div>
<div style="font-family: Consolas, Courier, monospace; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="font-family: Consolas, Courier, monospace; font-size: 12pt; color: rgb(0, 0, 0);">
Reviewed-by: Andrei Warkentin <awarkentin@vmware.com></div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> Jeremy Linton <jeremy.linton@arm.com><br>
<b>Sent:</b> Friday, October 1, 2021 7:52 PM<br>
<b>To:</b> devel@edk2.groups.io <devel@edk2.groups.io><br>
<b>Cc:</b> pete@akeo.ie <pete@akeo.ie>; ardb+tianocore@kernel.org <ardb+tianocore@kernel.org>; leif@nuviainc.com <leif@nuviainc.com>; Andrei Warkentin <awarkentin@vmware.com>; Sunny.Wang@arm.com <Sunny.Wang@arm.com>; samer.el-haj-mahmoud@arm.com <samer.el-haj-mahmoud@arm.com>;
Jeremy Linton <jeremy.linton@arm.com><br>
<b>Subject:</b> [PATCH 2/5] Platform/RaspberryPi: Expand locking to cover return data</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText">While debugging problems with the GET/SET_CLOCK mailbox calls it appeared<br>
that the locking in most of the mailbox commands isn't perfectly<br>
correct. All UEFI firmware calls to the RPi mailbox share a single<br>
mDmaBuffer which is used to fill out the command passed to the vc firmware,<br>
and record its response. The buffer is protected by mMailboxLock, yet in<br>
many cases the result of the request is copied from the buffer after the<br>
lock has been released. This doesn't currently appear to be causing any<br>
problems, but should probably be fixed anyway.<br>
<br>
There are a couple other minor tweaks in this patch that are hard to<br>
justify on their own, one is a bit of whitespace cleanup, and the other is<br>
the addition of a debug message to print the returned clock rate for the<br>
requested clock. This latter print would have immediatly shown that the vc<br>
firmware was returning 0 as the emmc clock rate rather than something<br>
reasonable.<br>
<br>
Signed-off-by: Jeremy Linton <jeremy.linton@arm.com><br>
---<br>
.../Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c | 102 ++++++++++++---------<br>
1 file changed, 59 insertions(+), 43 deletions(-)<br>
<br>
diff --git a/Platform/RaspberryPi/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c b/Platform/RaspberryPi/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c<br>
index bf74148bbb..29719aa5ec 100644<br>
--- a/Platform/RaspberryPi/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c<br>
+++ b/Platform/RaspberryPi/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c<br>
@@ -203,7 +203,6 @@ RpiFirmwareSetPowerState (<br>
<br>
Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);<br>
<br>
- ReleaseSpinLock (&mMailboxLock);<br>
<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
@@ -219,6 +218,7 @@ RpiFirmwareSetPowerState (<br>
__FUNCTION__, PowerState ? "en" : "dis", DeviceId));<br>
Status = EFI_DEVICE_ERROR;<br>
}<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
<br>
return Status;<br>
}<br>
@@ -266,18 +266,20 @@ RpiFirmwareGetArmMemory (<br>
<br>
Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);<br>
<br>
- ReleaseSpinLock (&mMailboxLock);<br>
<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
DEBUG ((DEBUG_ERROR,<br>
"%a: mailbox transaction error: Status == %r, Response == 0x%x\n",<br>
__FUNCTION__, Status, Cmd->BufferHead.Response));<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
return EFI_DEVICE_ERROR;<br>
}<br>
<br>
*Base = Cmd->TagBody.Base;<br>
*Size = Cmd->TagBody.Size;<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
+<br>
return EFI_SUCCESS;<br>
}<br>
<br>
@@ -323,17 +325,18 @@ RpiFirmwareGetMacAddress (<br>
<br>
Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);<br>
<br>
- ReleaseSpinLock (&mMailboxLock);<br>
-<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
DEBUG ((DEBUG_ERROR,<br>
"%a: mailbox transaction error: Status == %r, Response == 0x%x\n",<br>
__FUNCTION__, Status, Cmd->BufferHead.Response));<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
return EFI_DEVICE_ERROR;<br>
}<br>
<br>
CopyMem (MacAddress, Cmd->TagBody.MacAddress, sizeof (Cmd->TagBody.MacAddress));<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
+<br>
return EFI_SUCCESS;<br>
}<br>
<br>
@@ -378,17 +381,17 @@ RpiFirmwareGetSerial (<br>
<br>
Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);<br>
<br>
- ReleaseSpinLock (&mMailboxLock);<br>
-<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
DEBUG ((DEBUG_ERROR,<br>
"%a: mailbox transaction error: Status == %r, Response == 0x%x\n",<br>
__FUNCTION__, Status, Cmd->BufferHead.Response));<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
return EFI_DEVICE_ERROR;<br>
}<br>
<br>
*Serial = Cmd->TagBody.Serial;<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
// Some platforms return 0 or 0x0000000010000000 for serial.<br>
// For those, try to use the MAC address.<br>
if ((*Serial == 0) || ((*Serial & 0xFFFFFFFF0FFFFFFFULL) == 0)) {<br>
@@ -441,17 +444,18 @@ RpiFirmwareGetModel (<br>
<br>
Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);<br>
<br>
- ReleaseSpinLock (&mMailboxLock);<br>
-<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
DEBUG ((DEBUG_ERROR,<br>
"%a: mailbox transaction error: Status == %r, Response == 0x%x\n",<br>
__FUNCTION__, Status, Cmd->BufferHead.Response));<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
return EFI_DEVICE_ERROR;<br>
}<br>
<br>
*Model = Cmd->TagBody.Model;<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
+<br>
return EFI_SUCCESS;<br>
}<br>
<br>
@@ -496,17 +500,18 @@ RpiFirmwareGetModelRevision (<br>
<br>
Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);<br>
<br>
- ReleaseSpinLock (&mMailboxLock);<br>
-<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
DEBUG ((DEBUG_ERROR,<br>
"%a: mailbox transaction error: Status == %r, Response == 0x%x\n",<br>
__FUNCTION__, Status, Cmd->BufferHead.Response));<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
return EFI_DEVICE_ERROR;<br>
}<br>
<br>
*Revision = Cmd->TagBody.Revision;<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
+<br>
return EFI_SUCCESS;<br>
}<br>
<br>
@@ -538,17 +543,18 @@ RpiFirmwareGetFirmwareRevision (<br>
<br>
Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);<br>
<br>
- ReleaseSpinLock (&mMailboxLock);<br>
-<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
DEBUG ((DEBUG_ERROR,<br>
"%a: mailbox transaction error: Status == %r, Response == 0x%x\n",<br>
__FUNCTION__, Status, Cmd->BufferHead.Response));<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
return EFI_DEVICE_ERROR;<br>
}<br>
<br>
*Revision = Cmd->TagBody.Revision;<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
+<br>
return EFI_SUCCESS;<br>
}<br>
<br>
@@ -831,18 +837,19 @@ RpiFirmwareGetFbSize (<br>
<br>
Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);<br>
<br>
- ReleaseSpinLock (&mMailboxLock);<br>
-<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
DEBUG ((DEBUG_ERROR,<br>
"%a: mailbox transaction error: Status == %r, Response == 0x%x\n",<br>
__FUNCTION__, Status, Cmd->BufferHead.Response));<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
return EFI_DEVICE_ERROR;<br>
}<br>
<br>
*Width = Cmd->TagBody.Width;<br>
*Height = Cmd->TagBody.Height;<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
+<br>
return EFI_SUCCESS;<br>
}<br>
<br>
@@ -872,16 +879,18 @@ RpiFirmwareFreeFb (VOID)<br>
Cmd->EndTag = 0;<br>
<br>
Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);<br>
- ReleaseSpinLock (&mMailboxLock);<br>
<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
DEBUG ((DEBUG_ERROR,<br>
"%a: mailbox transaction error: Status == %r, Response == 0x%x\n",<br>
__FUNCTION__, Status, Cmd->BufferHead.Response));<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
return EFI_DEVICE_ERROR;<br>
}<br>
<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
+<br>
return EFI_SUCCESS;<br>
}<br>
<br>
@@ -935,19 +944,20 @@ RpiFirmwareAllocFb (<br>
<br>
Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);<br>
<br>
- ReleaseSpinLock (&mMailboxLock);<br>
-<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
DEBUG ((DEBUG_ERROR,<br>
"%a: mailbox transaction error: Status == %r, Response == 0x%x\n",<br>
__FUNCTION__, Status, Cmd->BufferHead.Response));<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
return EFI_DEVICE_ERROR;<br>
}<br>
<br>
*Pitch = Cmd->Pitch.Pitch;<br>
*FbBase = Cmd->AllocFb.AlignmentBase - BCM2836_DMA_DEVICE_OFFSET;<br>
*FbSize = Cmd->AllocFb.Size;<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
+<br>
return EFI_SUCCESS;<br>
}<br>
<br>
@@ -999,13 +1009,12 @@ RpiFirmwareGetCommmandLine (<br>
<br>
Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);<br>
<br>
- ReleaseSpinLock (&mMailboxLock);<br>
-<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
DEBUG ((DEBUG_ERROR,<br>
"%a: mailbox transaction error: Status == %r, Response == 0x%x\n",<br>
__FUNCTION__, Status, Cmd->BufferHead.Response));<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
return EFI_DEVICE_ERROR;<br>
}<br>
<br>
@@ -1013,6 +1022,7 @@ RpiFirmwareGetCommmandLine (<br>
if (Cmd->TagHead.TagValueSize >= BufferSize &&<br>
Cmd->CommandLine[Cmd->TagHead.TagValueSize - 1] != '\0') {<br>
DEBUG ((DEBUG_ERROR, "%a: insufficient buffer size\n", __FUNCTION__));<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
return EFI_OUT_OF_RESOURCES;<br>
}<br>
<br>
@@ -1026,6 +1036,7 @@ RpiFirmwareGetCommmandLine (<br>
CommandLine[Cmd->TagHead.TagValueSize] = '\0';<br>
}<br>
<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
return EFI_SUCCESS;<br>
}<br>
<br>
@@ -1075,18 +1086,20 @@ RpiFirmwareSetClockRate (<br>
Cmd->TagBody.SkipTurbo = SkipTurbo ? 1 : 0;<br>
Cmd->EndTag = 0;<br>
<br>
+ DEBUG ((DEBUG_ERROR, "%a: Request clock rate %X = %d\n", __FUNCTION__, ClockId, ClockRate));<br>
Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);<br>
<br>
- ReleaseSpinLock (&mMailboxLock);<br>
-<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
DEBUG ((DEBUG_ERROR,<br>
"%a: mailbox transaction error: Status == %r, Response == 0x%x\n",<br>
__FUNCTION__, Status, Cmd->BufferHead.Response));<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
return EFI_DEVICE_ERROR;<br>
}<br>
<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
+<br>
return EFI_SUCCESS;<br>
}<br>
<br>
@@ -1131,20 +1144,23 @@ RpiFirmwareGetClockRate (<br>
Cmd->TagHead.TagValueSize = 0;<br>
Cmd->TagBody.ClockId = ClockId;<br>
Cmd->EndTag = 0;<br>
-<br>
+ <br>
Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);<br>
<br>
- ReleaseSpinLock (&mMailboxLock);<br>
-<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
DEBUG ((DEBUG_ERROR,<br>
"%a: mailbox transaction error: Status == %r, Response == 0x%x\n",<br>
__FUNCTION__, Status, Cmd->BufferHead.Response));<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
return EFI_DEVICE_ERROR;<br>
}<br>
<br>
*ClockRate = Cmd->TagBody.ClockRate;<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
+<br>
+ DEBUG ((DEBUG_ERROR, "%a: Get Clock Rate return: ClockRate=%d ClockId=%X\n", __FUNCTION__, *ClockRate, ClockId));<br>
+<br>
return EFI_SUCCESS;<br>
}<br>
<br>
@@ -1191,7 +1207,7 @@ RpiFirmwareGetMinClockRate (<br>
{<br>
return RpiFirmwareGetClockRate (ClockId, RPI_MBOX_GET_MIN_CLOCK_RATE, ClockRate);<br>
}<br>
-<br>
+<br>
#pragma pack()<br>
typedef struct {<br>
UINT32 ClockId;<br>
@@ -1236,16 +1252,17 @@ RpiFirmwareSetClockState (<br>
<br>
Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);<br>
<br>
- ReleaseSpinLock (&mMailboxLock);<br>
-<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
DEBUG ((DEBUG_ERROR,<br>
"%a: mailbox transaction error: Status == %r, Response == 0x%x\n",<br>
__FUNCTION__, Status, Cmd->BufferHead.Response));<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
return EFI_DEVICE_ERROR;<br>
}<br>
<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
+<br>
return EFI_SUCCESS;<br>
}<br>
<br>
@@ -1297,16 +1314,15 @@ RpiFirmwareSetGpio (<br>
<br>
Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);<br>
<br>
- ReleaseSpinLock (&mMailboxLock);<br>
-<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
DEBUG ((DEBUG_ERROR,<br>
"%a: mailbox transaction error: Status == %r, Response == 0x%x\n",<br>
__FUNCTION__, Status, Cmd->BufferHead.Response));<br>
}<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
}<br>
-<br>
+<br>
STATIC<br>
VOID<br>
EFIAPI<br>
@@ -1361,8 +1377,6 @@ RpiFirmwareNotifyXhciReset (<br>
<br>
Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);<br>
<br>
- ReleaseSpinLock (&mMailboxLock);<br>
-<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
DEBUG ((DEBUG_ERROR,<br>
@@ -1370,6 +1384,8 @@ RpiFirmwareNotifyXhciReset (<br>
__FUNCTION__, Status, Cmd->BufferHead.Response));<br>
}<br>
<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
+<br>
return Status;<br>
}<br>
<br>
@@ -1424,8 +1440,6 @@ RpiFirmwareNotifyGpioGetCfg (<br>
<br>
*Polarity = Cmd->TagBody.Polarity;<br>
<br>
- ReleaseSpinLock (&mMailboxLock);<br>
-<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
DEBUG ((DEBUG_ERROR,<br>
@@ -1433,6 +1447,8 @@ RpiFirmwareNotifyGpioGetCfg (<br>
__FUNCTION__, Status, Cmd->BufferHead.Response));<br>
}<br>
<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
+<br>
return Status;<br>
}<br>
<br>
@@ -1471,8 +1487,8 @@ RpiFirmwareNotifyGpioSetCfg (<br>
<br>
Status = RpiFirmwareNotifyGpioGetCfg (Gpio, &Result);<br>
if (EFI_ERROR (Status)) {<br>
- DEBUG ((DEBUG_ERROR, "%a: Failed to get GPIO polarity\n", __FUNCTION__));<br>
- Result = 0; //default polarity<br>
+ DEBUG ((DEBUG_ERROR, "%a: Failed to get GPIO polarity\n", __FUNCTION__));<br>
+ Result = 0; //default polarity<br>
}<br>
<br>
<br>
@@ -1488,7 +1504,7 @@ RpiFirmwareNotifyGpioSetCfg (<br>
Cmd->BufferHead.Response = 0;<br>
Cmd->TagHead.TagId = RPI_MBOX_SET_GPIO_CONFIG;<br>
Cmd->TagHead.TagSize = sizeof (Cmd->TagBody);<br>
-<br>
+<br>
Cmd->TagBody.Gpio = 128 + Gpio;<br>
Cmd->TagBody.Direction = Direction;<br>
Cmd->TagBody.Polarity = Result;<br>
@@ -1501,17 +1517,17 @@ RpiFirmwareNotifyGpioSetCfg (<br>
<br>
Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);<br>
<br>
- ReleaseSpinLock (&mMailboxLock);<br>
-<br>
if (EFI_ERROR (Status) ||<br>
Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {<br>
DEBUG ((DEBUG_ERROR,<br>
"%a: mailbox transaction error: Status == %r, Response == 0x%x\n",<br>
__FUNCTION__, Status, Cmd->BufferHead.Response));<br>
}<br>
-<br>
- RpiFirmwareSetGpio (Gpio,!State);<br>
-<br>
+<br>
+ ReleaseSpinLock (&mMailboxLock);<br>
+<br>
+ RpiFirmwareSetGpio (Gpio,!State);<br>
+<br>
<br>
return Status;<br>
}<br>
@@ -1540,7 +1556,7 @@ STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL mRpiFirmwareProtocol = {<br>
RPiFirmwareGetModelInstalledMB,<br>
RpiFirmwareNotifyXhciReset,<br>
RpiFirmwareGetCurrentClockState,<br>
- RpiFirmwareSetClockState,<br>
+ RpiFirmwareSetClockState,<br>
RpiFirmwareNotifyGpioSetCfg<br>
};<br>
<br>
-- <br>
2.13.7<br>
<br>
</div>
</span></font></div>
</body>
</html>
<div width="1" style="color:white;clear:both">_._,_._,_</div> <hr> Groups.io Links:<p> You receive all messages sent to this group. <p> <a target="_blank" href="https://edk2.groups.io/g/devel/message/81388">View/Reply Online (#81388)</a> | | <a target="_blank" href="https://groups.io/mt/86014862/1813853">Mute This Topic</a> | <a href="https://edk2.groups.io/g/devel/post">New Topic</a><br> <a href="https://edk2.groups.io/g/devel/editsub/1813853">Your Subscription</a> | <a href="mailto:devel+owner@edk2.groups.io">Contact Group Owner</a> | <a href="https://edk2.groups.io/g/devel/unsub">Unsubscribe</a> [edk2-devel-archive@redhat.com]<br> <div width="1" style="color:white;clear:both">_._,_._,_</div>