Good day,

Thank you, Laszlo, for your ambition to introduce stricter code style 
enforcements. Sorry to "hijack" the actual topic (I did not CC anyone on 
purpose, as this is mostly a separate topic and I'd like a quick comment 
first), but this seems like a good occasion to mention another few bad 
practices edk2 has been following. Mainly, I'd like to call *some* 
attention to quality problems in the code base while this has some 
traction, and cause a discussion on whether and how those are to be 
approached.

Thank you for your time.

Regards,
Marvin



"inadequate type punning":
e.g. 
https://github.com/tianocore/edk2/blob/fcdedafd97c8f18c33a63d26b954e5dbaee81a2b/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.c#L446

This is mostly about the infamous "Strict Aliasing" rule, which is 
basically:
"An object shall have its stored value accessed only by an lvalue 
expression that has one of the
following types:
— a type compatible with the effective type of the object,
— a qualifed version of a type compatible with the effective type of the 
object,
— a type that is the signed or unsigned type corresponding to the 
effective type of the object,
— a type that is the signed or unsigned type corresponding to a qualifed 
version of the effective
type of the object,
— an aggregate or union type that includes one of the aforementioned 
types among its members
(including, recursively, a member of a subaggregate or contained union), or
— a character type."
C18 (ISO/IEC 9899:2018), 6.5.7 (exists, though has been updated, since C90)

Currently optimisations based on this are disabled. This is a bit nasty 
to work around if *seriously* needed when sticking to C90, I can only 
think of memcpy right now. However, even though there are compilers that 
do not fully support C99 (ahem, Microsoft :) ), type-punning by unions 
should be supported by them all, and has been legal as of C99, where the 
following part has been dropped from the standard:
"With one exception, if a member of a union object is accessed after a 
value has been stored in a different member of the object, the behavior 
is implementation-defined."
C90 (ISO/IEC 9899:1990), 6.3.2.3



"pointer unions":
e.g. 
https://github.com/tianocore/edk2/blob/fcdedafd97c8f18c33a63d26b954e5dbaee81a2b/MdePkg/Include/IndustryStandard/SmBios.h#L2592

While the idea behind them is certainly style preference, using a union 
of pointers prevents two important things over a union of structs.

1) CONST declaration: When defining a variable of a union type 
containing pointers as CONST, speaking of its members, they are all 
going to be CONST pointers to arbitrary memory and not arbitrary 
pointers to CONST memory. With a union of structs, you can have either 
as required (e.g. CONST UNION_TYPE *union, or UNION_TYPE *COST union).

2) Well-defined header inspection:
"if a union contains several structures that share a common initial 
sequence [...], it is permitted to inspect the common initial part of 
any of them anywhere that a declaration of the completed type of the 
union is visible"
C18 (ISO/IEC 9899:2018), 6.5.2.3.6 (exists since at least C90)

This guarantee can be used to inspect the type defined in a common 
header (e.g. SMBIOS_STRUCTURE) and the process the type-specific data by 
accessing the appropiate member (e.g. SMBIOS_TABLE_TYPE0) legally. Plain 
casts and "pointer union" accesses are illegal as per the "inadequate 
type punning" point above.



"casting away CONST":
e.g. 
https://github.com/tianocore/edk2/blob/fcdedafd97c8f18c33a63d26b954e5dbaee81a2b/MdePkg/Library/BaseIoLibIntrinsic/IoLibMmioBuffer.c#L236

This should be obvious as Undefined Behaviour because memory previously 
guaranteed to be read-only is returned as a pointer to memory that 
allows writing, but for easier lookup, here's the related rule:
"the left operand has atomic, qualifed, or unqualifed pointer type, and 
[...] the type pointed to by the left has all the qualifers of the type 
pointed to by the right"
C18 (ISO/IEC 9899:2018), 6.5.16.1 (exists since at least C90)



"structs with trailing 1-length array"
e.g. 
https://github.com/tianocore/edk2/blob/fcdedafd97c8f18c33a63d26b954e5dbaee81a2b/MdePkg/Include/Guid/FileInfo.h#L51

This is undefined as per:
"The behavior is undefned in the following circumstances:
[...]
— Addition or subtraction of a pointer into, or just beyond, an array 
object and an integer type produces a result that does not point into, 
or just beyond, the same array object (6.5.6).
— Addition or subtraction of a pointer into, or just beyond, an array 
object and an integer type produces a result that points just beyond the 
array object and is used as the operand of a unary * operator that is 
evaluated (6.5.6).
— Pointers that do not point into, or just beyond, the same array object 
are subtracted (6.5.6)."
C18 (ISO/IEC 9899:2018), J.2 (exists since at least C90)

Same as above, while not all compilers fully support C99, flexible 
arrays should be support by all reasonably new compilers and allow a 
legal declaration and usage where this hack is in place. At worst, a 
macro could be provided to declare a [1] vs a [] array on demand and a 
requirement be introduced to have a "SIZE_OF_" macro for each such 
struct, but my personal preference would be to just enforce flexible arrays.



"Missing security checks for external data":
e.g. 
https://github.com/tianocore/edk2/blob/fcdedafd97c8f18c33a63d26b954e5dbaee81a2b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c#L943

The given example misses an alignment verification of the resulting 
pointer (which technically has to be verified *before* casting), as 
documented here:
"The behavior is undefined in the following circumstances:
[...]
— Conversion between two pointer types produces a result that is 
incorrectly aligned (6.3.2.3)."
C18 (ISO/IEC 9899:2018), J.2 (exists since at least C90)

There are more such issues throughout the codebase, including missing 
overflow and (or flawed, see before) bounds checks, however I cannot 
find such quickly.



"signed int BIT definitions":
e.g. 
https://github.com/tianocore/edk2/blob/fcdedafd97c8f18c33a63d26b954e5dbaee81a2b/MdePkg/Include/Base.h#L348

Fixing this would be prone to regressions, but I'd like to add it for 
tracking purposes. Related discussion can be found down the chain here: 
https://lists.01.org/pipermail/edk2-devel/2018-February/021919.html



Am 17.09.2019 um 21:49 schrieb Laszlo Ersek:
> Repository: https://github.com/lersek/edk2.git
> Branch:     voidptr
> 
> The UEFI / PI / Shell specifications define a number of standard types
> as pointers to VOID. This is arguably a design mistake; those types
> should have been pointers to distinct incomplete union or structure
> types. Here's why:
> 
> Roughly paraphrasing the constraints from ISO C99 "6.5.16.1 Simple
> assignment" and "6.5.4 Cast operators", any pointer-to-object type
> converts implicitly to, and from, pointer-to-void, provided const /
> volatile qualifications are not relaxed. Such implicit conversions
> prevent compilers from catching at least the following two kinds of
> coding mistakes:
> 
> - mixing up one type with another (for example, EFI_HANDLE with
>    EFI_EVENT),
> 
> - getting the depth of indirection wrong (for example, mixing up
>    (EFI_HANDLE*) with EFI_HANDLE).
> 
> This series first separates these standard types from each other, in the
> first patch, which is *not* being proposed for merging. This unmasks a
> number of warts (semantic issues, or actual bugs) in the source code, in
> the form of build breakages. The rest of the series works through those
> breakages, cleaning and fixing the code.
> 
> Every DSC file in the edk2 tree was built for at least one of the NOOPT,
> DEBUG, RELEASE targets (NOOPT being preferred), with the GCC48 toolchain
> (for IA32 / X64) and the GCC5 toolchain (for ARM / AARCH64). Of course,
> the build arches were restricted to the SUPPORTED_ARCHITECTURES stated
> in the individual DSC files.
> 
> There were two exceptions to the above rule: DynamicTablesPkg was only
> build-tested with AARCH64 (despite its SUPPORTED_ARCHITECTURES), given
> that 32-bit ARM has no ACPI bindings. StandaloneMmPkg too was only
> build-tested with AARCH64; it doesn't actually support IA32/X64 yet.
> 
> Regarding boot & runtime tests, ArmVirtQemu on AARCH64 was tested with
> booting to the OS (RHEL7). Furthermore, I exercised OVMF with my usual
> boot and S3 tests, covering IA32, IA32X64, and X64. Finally, some other
> individual tests (noted per patch) were done with OVMF.
> 
> Cc: Achin Gupta <achin.gu...@arm.com>
> Cc: Andrew Fish <af...@apple.com>
> Cc: Anthony Perard <anthony.per...@citrix.com>
> Cc: Ard Biesheuvel <ard.biesheu...@linaro.org>
> Cc: Benjamin You <benjamin....@intel.com>
> Cc: Chao Zhang <chao.b.zh...@intel.com>
> Cc: Dandan Bi <dandan...@intel.com>
> Cc: David Woodhouse <dw...@infradead.org>
> Cc: Eric Dong <eric.d...@intel.com>
> Cc: Guo Dong <guo.d...@intel.com>
> Cc: Hao A Wu <hao.a...@intel.com>
> Cc: Jaben Carsey <jaben.car...@intel.com>
> Cc: Jian J Wang <jian.j.w...@intel.com>
> Cc: Jian Wang <jian.j.w...@intel.com>
> Cc: Jiaxin Wu <jiaxin...@intel.com>
> Cc: Jiewen Yao <jiewen....@intel.com>
> Cc: Jordan Justen <jordan.l.jus...@intel.com>
> Cc: Julien Grall <julien.gr...@arm.com>
> Cc: Leif Lindholm <leif.lindh...@linaro.org>
> Cc: Liming Gao <liming....@intel.com>
> Cc: Maurice Ma <maurice...@intel.com>
> Cc: Michael D Kinney <michael.d.kin...@intel.com>
> Cc: Ray Ni <ray...@intel.com>
> Cc: Siyuan Fu <siyuan...@intel.com>
> Cc: Supreeth Venkatesh <supreeth.venkat...@arm.com>
> Cc: Zhichao Gao <zhichao....@intel.com>
> 
> Thanks
> Laszlo
> 
> Laszlo Ersek (35):
>    DO NOT APPLY: edk2: turn standard handle types into pointers to
>      non-VOID
>    EmbeddedPkg: add missing EFIAPI calling convention specifiers
>    EmbeddedPkg/AndroidFastbootTransportTcpDxe: fix DestroyChild() call
>    EmbeddedPkg/Universal/MmcDxe: "fix" CloseProtocol() call in
>      BindingStop()
>    EmulatorPkg/DxeTimerLib: drop superfluous cast
>    EmulatorPkg: stop abusing EFI_HANDLE for keystroke notify registration
>    MdeModulePkg: fix cast in GetModuleInfoFromHandle() calls
>    MdeModulePkg/UefiHiiLib: stop using EFI_HANDLE in place of
>      EFI_HII_HANDLE
>    MdeModulePkg: stop abusing EFI_EVENT for protocol notify registration
>    MdeModulePkg/PlatformVarCleanupLib: fix HiiConstructConfigHdr() call
>    MdeModulePkg: document workaround for EFI_RUNTIME_EVENT_ENTRY PI spec
>      bug
>    MdeModulePkg: stop abusing EFI_HANDLE for keystroke notify
>      registration
>    MdeModulePkg: PEI Core: clean up "AprioriFile" handling in
>      FindFileEx()
>    MdeModulePkg: fix UninstallMultipleProtocolInterfaces() calls
>    MdeModulePkg/PiSmmCore: make type punning consistent
>    MdeModulePkg/S3SaveState: cast Position for S3BootScriptLib explicitly
>    MdePkg/DxeServicesLib: remove bogus cast
>    NetworkPkg/DxeNetLib: fix type typo in NetLibGetMacAddress()
>    NetworkPkg: fix CloseProtocol & UninstallMultipleProtocolInterfaces
>      calls
>    NetworkPkg/Ip4Dxe: fix NetLibDestroyServiceChild() call
>    NetworkPkg/TcpDxe: fix SockFreeFoo() parameter list
>    OvmfPkg/XenBusDxe: fix UninstallMultipleProtocolInterfaces() call
>    OvmfPkg/VirtioNetDxe: fix SignalEvent() call
>    OvmfPkg/PlatformDxe: fix EFI_HII_HANDLE parameters of internal
>      functions
>    OvmfPkg/VideoDxe: document EFI_EDID_OVERRIDE_PROTOCOL.GetEdid() call
>    SecurityPkg: fix UninstallMultipleProtocolInterfaces() calls
>    SecurityPkg: stop abusing EFI_EVENT for protocol notify registration
>    ShellPkg/UefiShellDriver1CommandsLib: fix parameter list typo
>    ShellPkg: stop using EFI_HANDLE in place of EFI_HII_HANDLE
>    ShellPkg: stop taking EFI_HANDLE in place of SHELL_FILE_HANDLE
>    ShellPkg/UefiShellDebug1CommandsLib: fix ShellCloseFile() call
>    ShellPkg/UefiShellLib: clarify workaround for unfixable EdkShell bug
>    StandaloneMmPkg/Core: stop abusing EFI_HANDLE for FwVolHeader tracking
>    UefiPayloadPkg/BlSupportPei: fix MMCONFIG assignment from XSDT
>    UefiPayloadPkg/BlSupportDxe: fix ReserveResourceInGcd() calls
> 
>   EmbeddedPkg/Drivers/AndroidFastbootTransportTcpDxe/FastbootTransportTcp.c   
>    |  2 +-
>   EmbeddedPkg/Drivers/ConsolePrefDxe/ConsolePrefDxe.c                         
>    |  1 +
>   EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118Dxe.c                                 
>    |  1 +
>   EmbeddedPkg/Drivers/SataSiI3132Dxe/SataSiI3132.h                            
>    | 32 ++++++--
>   EmbeddedPkg/Drivers/SataSiI3132Dxe/SiI3132AtaPassThru.c                     
>    |  8 ++
>   EmbeddedPkg/GdbStub/GdbStubInternal.h                                       
>    |  9 +++
>   EmbeddedPkg/MetronomeDxe/Metronome.c                                        
>    |  1 +
>   EmbeddedPkg/Universal/MmcDxe/Mmc.c                                          
>    |  5 +-
>   EmulatorPkg/EmuGopDxe/GopInput.c                                            
>    |  4 +-
>   EmulatorPkg/Library/DxeTimerLib/DxeTimerLib.c                               
>    |  2 +-
>   MdeModulePkg/Bus/I2c/I2cDxe/I2cBus.c                                        
>    |  2 +-
>   MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c                             
>    |  2 +-
>   MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c                           
>    |  6 +-
>   MdeModulePkg/Bus/Pci/PciSioSerialDxe/Serial.c                               
>    |  2 +-
>   MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.c                                       
>    |  2 +-
>   MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c                                  
>    |  2 +-
>   MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassImpl.c                        
>    |  2 +-
>   MdeModulePkg/Core/Dxe/Event/Event.c                                         
>    |  8 ++
>   MdeModulePkg/Core/Dxe/Event/Event.h                                         
>    |  2 +-
>   MdeModulePkg/Core/Dxe/Hand/Handle.h                                         
>    |  2 +-
>   MdeModulePkg/Core/Pei/FwVol/FwVol.c                                         
>    |  2 +-
>   MdeModulePkg/Core/Pei/FwVol/FwVol.h                                         
>    |  2 +-
>   MdeModulePkg/Core/PiSmmCore/PiSmmCore.h                                     
>    |  2 +-
>   MdeModulePkg/Core/PiSmmCore/Smi.c                                           
>    |  8 +-
>   MdeModulePkg/Core/RuntimeDxe/Runtime.c                                      
>    | 10 ++-
>   MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c          
>    | 12 +--
>   MdeModulePkg/Library/PlatformVarCleanupLib/PlatVarCleanupLib.c              
>    |  6 +-
>   MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c          
>    |  8 +-
>   MdeModulePkg/Library/UefiHiiLib/HiiString.c                                 
>    |  4 +-
>   MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiSdt.h                          
>    |  2 +-
>   MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveState.c                    
>    |  4 +-
>   MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.c                 
>    |  4 +-
>   MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c                 
>    |  2 +-
>   MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c                       
>    |  4 +-
>   MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.c        
>    |  2 +-
>   MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c        
>    |  2 +-
>   MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h                         
>    |  2 +-
>   MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c                        
>    |  2 +-
>   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c                    
>    |  2 +-
>   MdePkg/Include/Pi/PiPeiCis.h                                                
>    |  6 +-
>   MdePkg/Include/Protocol/AcpiSystemDescriptionTable.h                        
>    |  3 +-
>   MdePkg/Include/Protocol/Bis.h                                               
>    |  3 +-
>   MdePkg/Include/Protocol/Eap.h                                               
>    |  3 +-
>   MdePkg/Include/Protocol/HiiFont.h                                           
>    |  3 +-
>   MdePkg/Include/Protocol/MmMp.h                                              
>    |  3 +-
>   MdePkg/Include/Protocol/S3SaveState.h                                       
>    |  2 +-
>   MdePkg/Include/Protocol/Shell.h                                             
>    |  3 +-
>   MdePkg/Include/Protocol/UserManager.h                                       
>    |  9 ++-
>   MdePkg/Include/Uefi/UefiBaseType.h                                          
>    |  6 +-
>   MdePkg/Include/Uefi/UefiInternalFormRepresentation.h                        
>    |  3 +-
>   MdePkg/Library/DxeServicesLib/DxeServicesLib.c                              
>    |  2 +-
>   NetworkPkg/DnsDxe/DnsDriver.c                                               
>    |  4 +-
>   NetworkPkg/IScsiDxe/IScsiConfig.c                                           
>    |  2 +-
>   NetworkPkg/Ip4Dxe/Ip4Driver.c                                               
>    |  2 +-
>   NetworkPkg/Ip4Dxe/Ip4If.c                                                   
>    |  4 +-
>   NetworkPkg/Ip6Dxe/Ip6Driver.c                                               
>    |  2 +-
>   NetworkPkg/Library/DxeNetLib/DxeNetLib.c                                    
>    |  2 +-
>   NetworkPkg/Mtftp4Dxe/Mtftp4Driver.c                                         
>    |  2 +-
>   NetworkPkg/TcpDxe/SockImpl.c                                                
>    |  4 +-
>   NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c                              
>    |  2 +-
>   OvmfPkg/Csm/BiosThunk/VideoDxe/BiosVideo.c                                  
>    |  6 +-
>   OvmfPkg/PlatformDxe/Platform.c                                              
>    |  4 +-
>   OvmfPkg/VirtioNetDxe/Events.c                                               
>    |  2 +-
>   OvmfPkg/XenBusDxe/XenBus.c                                                  
>    |  2 +-
>   SecurityPkg/HddPassword/HddPasswordDxe.c                                    
>    |  2 +-
>   SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDriver.c                               
>    |  2 +-
>   SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDriver.c                              
>    |  2 +-
>   
> SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDriver.c
>  |  2 +-
>   ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c                               
>    |  6 +-
>   ShellPkg/DynamicCommand/DpDynamicCommand/Dp.h                               
>    |  4 +-
>   ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.c                           
>    |  6 +-
>   ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.h                           
>    |  4 +-
>   ShellPkg/Include/Library/ShellCommandLib.h                                  
>    |  2 +-
>   ShellPkg/Include/Library/ShellLib.h                                         
>    |  4 +-
>   ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c                
>    |  2 +-
>   ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c          
>    |  2 +-
>   ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c                  
>    |  2 +-
>   ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h                  
>    |  2 +-
>   ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c               
>    |  2 +-
>   ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.c    
>    |  2 +-
>   ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.h    
>    |  2 +-
>   ShellPkg/Library/UefiShellDriver1CommandsLib/Connect.c                      
>    |  4 +-
>   ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.c  
>    |  2 +-
>   ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h  
>    |  2 +-
>   ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c    
>    |  2 +-
>   ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h    
>    |  2 +-
>   ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c                            
>    |  2 +-
>   ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c    
>    |  2 +-
>   ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h    
>    |  2 +-
>   ShellPkg/Library/UefiShellLevel3CommandsLib/Touch.c                         
>    |  2 +-
>   ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.c    
>    |  2 +-
>   ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.h    
>    |  2 +-
>   ShellPkg/Library/UefiShellLib/UefiShellLib.c                                
>    | 26 ++++++-
>   
> ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c  
>  |  2 +-
>   
> ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h  
>  |  2 +-
>   
> ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.c  
>  |  2 +-
>   
> ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.h  
>  |  2 +-
>   StandaloneMmPkg/Core/Dispatcher.c                                           
>    | 80 +++++++++++---------
>   StandaloneMmPkg/Core/FwVol.c                                                
>    | 16 ++--
>   StandaloneMmPkg/Core/StandaloneMmCore.h                                     
>    |  4 +-
>   UefiPayloadPkg/BlSupportDxe/BlSupportDxe.c                                  
>    |  4 +-
>   UefiPayloadPkg/BlSupportPei/BlSupportPei.c                                  
>    | 19 +++--
>   102 files changed, 294 insertions(+), 194 deletions(-)
> 

-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#47861): https://edk2.groups.io/g/devel/message/47861
Mute This Topic: https://groups.io/mt/34180197/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to