From 69a42b73a41e9782b493ce5781d09e75008fdaeb Mon Sep 17 00:00:00 2001 From: Kun Qin Date: Thu, 24 Apr 2025 16:57:44 -0700 Subject: [PATCH 1/3] MdePkg: BaseLib: Add UUID-GUID conversion function With interactions between Standalone MM partitions and normal UEFI environment, there is constant need to convert UUID to GUID and back. This change added 2 new interfaces to BaseLib that support such usage. Signed-off-by: Kun Qin --- MdePkg/Include/Library/BaseLib.h | 95 ++++++++++++++++++ MdePkg/Library/BaseLib/BaseLib.inf | 1 + MdePkg/Library/BaseLib/ConvertGuidUuid.c | 121 +++++++++++++++++++++++ 3 files changed, 217 insertions(+) create mode 100644 MdePkg/Library/BaseLib/ConvertGuidUuid.c diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/BaseLib.h index 9658026d9c60..db11732c8b9d 100644 --- a/MdePkg/Include/Library/BaseLib.h +++ b/MdePkg/Include/Library/BaseLib.h @@ -4715,6 +4715,101 @@ BitFieldCountOnes64 ( IN UINTN EndBit ); +/******************************************************************************* + + UUID (Universally Unique IDentifier), as defined in RFC4122 + (https://datatracker.ietf.org/doc/html/rfc4122#section-4.1), is a 128-bit number + used to uniquely identify information in computer systems. + + UUIDs contains 5 fields: + - time_low: 32 bits + - time_mid: 16 bits + - time_hi_and_version: 16 bits + - clock_seq_hi_and_reserved: 8 bits + - clock_seq_low: 8 bits + - node: 8 bits * 6 + + Each field encoded with the Most Significant Byte first (known as network byte + order, or big-endian). + + GUID (Globally Unique Identifier), on the other hand, is a 128-bit number used + in UEFI environments, which is similar to UUID but has a different byte order + in memory. See https://uefi.org/specs/UEFI/2.11/Apx_A_GUID_and_Time_Formats.html + + GUID also contains 5 fields: + - TimeLow: 32 bits + - TimeMid: 16 bits + - TimeHiAndVersion: 16 bits + - ClockSeqHighAndReserved: 16 bits + - ClockSeqLow: 8 bits + - Node: 8 bits * 6 + + TimeLow, TimeMid, TimeHighAndVersion fields in the EFI are encoded with the Least + Significant Byte first (also known as little-endian). + + Example: + Consider the same string representation/registry format for MM communication v2: + "378daedc-f06b-4446-8314-40ab933c87a3" + + In UUID format, it is represented as: + - Data fields: + - time_low: 0x37 0x8d 0xae 0xdc (0x378daedc in big-endian) + - time_mid: 0xf0 0x6b (0xf06b in big-endian) + - time_hi_and_version: 0x44 0x46 (0x4446 in big-endian) + - clock_seq_hi_and_reserved: 0x83 + - clock_seq_low: 0x14 + - node: 0x00, 0xab, 0x93, 0x3c, 0x87, 0xa3 + - Byte representation in memory: + - 37 8d ae dc f0 6b 44 46 83 14 40 ab 93 3c 87 a3 + + However, in GUID format, it is represented as: + - Data fields: + - TimeLow: 0xdc 0xae 0x8d 0x37 (0x378daedc in little-endian) + - TimeMid: 0x6b 0xf0 (0xf06b in little-endian) + - TimeHiAndVersion: 0x46 0x44 (0x4446 in little-endian) + - ClockSeqHighAndReserved: 0x83 + - ClockSeqLow: 0x14 + - Node: 0x00, 0xab, 0x93, 0x3c, 0x87, 0xa3 + - Byte representation in memory: + - dc ae 8d 37 6b f0 46 44 83 14 40 ab 93 3c 87 a3 + +*******************************************************************************/ + +/** + This function converts a GUID in UEFI format to a UUID in RFC4122 format. + + The conversion is done by swapping the byte order of the TimeLow, TimeMid, and + TimeHiAndVersion fields, while keeping the ClockSeq and Node fields unchanged. + + @param [in] FromGuid GUID in format to be converted to UUID RFC4122 format. + @param [out] ToUuid Pointer to a GUID structure that will hold the converted + UUID in RFC4122 format. +**/ +VOID +EFIAPI +ConvertGuidToUuid ( + IN GUID *FromGuid, + OUT GUID *ToUuid + ); + +/** + This function converts a UUID in RFC4122 format to a GUID in UEFI format. + + The conversion is done by swapping the byte order of the time_low, time_mid, and + time_hi_and_version fields, while keeping the ClockSeq and Node fields unchanged. + This function is symmetric to ConvertGuidToUuid. + + @param [in] FromUuid UUID in RFC4122 format to be converted to GUID in UEFI format. + @param [out] ToGuid Pointer to a GUID structure that will hold the converted + GUID in UEFI format. +**/ +VOID +EFIAPI +ConvertUuidToGuid ( + IN GUID *FromUuid, + OUT GUID *ToGuid + ); + // // Base Library Checksum Functions // diff --git a/MdePkg/Library/BaseLib/BaseLib.inf b/MdePkg/Library/BaseLib/BaseLib.inf index 317d32cf68a4..ec40349654b3 100644 --- a/MdePkg/Library/BaseLib/BaseLib.inf +++ b/MdePkg/Library/BaseLib/BaseLib.inf @@ -55,6 +55,7 @@ DivS64x64Remainder.c ARShiftU64.c BitField.c + ConvertGuidUuid.c CpuDeadLoop.c Cpu.c LinkedList.c diff --git a/MdePkg/Library/BaseLib/ConvertGuidUuid.c b/MdePkg/Library/BaseLib/ConvertGuidUuid.c new file mode 100644 index 000000000000..85a3d6340992 --- /dev/null +++ b/MdePkg/Library/BaseLib/ConvertGuidUuid.c @@ -0,0 +1,121 @@ +/** @file + Convert 128 bit unique identifier between GUID and UUID format. + + Copyright (c) 2024, Arm Limited. All rights reserved.
+ Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include "BaseLibInternals.h" + +/******************************************************************************* + + UUID (Universally Unique IDentifier), as defined in RFC4122 + (https://datatracker.ietf.org/doc/html/rfc4122#section-4.1), is a 128-bit number + used to uniquely identify information in computer systems. + + UUIDs contains 5 fields: + - time_low: 32 bits + - time_mid: 16 bits + - time_hi_and_version: 16 bits + - clock_seq_hi_and_reserved: 8 bits + - clock_seq_low: 8 bits + - node: 8 bits * 6 + + Each field encoded with the Most Significant Byte first (known as network byte + order, or big-endian). + + GUID (Globally Unique Identifier), on the other hand, is a 128-bit number used + in UEFI environments, which is similar to UUID but has a different byte order + in memory. See https://uefi.org/specs/UEFI/2.11/Apx_A_GUID_and_Time_Formats.html + + GUID also contains 5 fields: + - TimeLow: 32 bits + - TimeMid: 16 bits + - TimeHiAndVersion: 16 bits + - ClockSeqHighAndReserved: 16 bits + - ClockSeqLow: 8 bits + - Node: 8 bits * 6 + + TimeLow, TimeMid, TimeHighAndVersion fields in the EFI are encoded with the Least + Significant Byte first (also known as little-endian). + + Example: + Consider the same string representation/registry format for MM communication v2: + "378daedc-f06b-4446-8314-40ab933c87a3" + + In UUID format, it is represented as: + - Data fields: + - time_low: 0x37 0x8d 0xae 0xdc (0x378daedc in big-endian) + - time_mid: 0xf0 0x6b (0xf06b in big-endian) + - time_hi_and_version: 0x44 0x46 (0x4446 in big-endian) + - clock_seq_hi_and_reserved: 0x83 + - clock_seq_low: 0x14 + - node: 0x00, 0xab, 0x93, 0x3c, 0x87, 0xa3 + - Byte representation in memory: + - 37 8d ae dc f0 6b 44 46 83 14 40 ab 93 3c 87 a3 + + However, in GUID format, it is represented as: + - Data fields: + - TimeLow: 0xdc 0xae 0x8d 0x37 (0x378daedc in little-endian) + - TimeMid: 0x6b 0xf0 (0xf06b in little-endian) + - TimeHiAndVersion: 0x46 0x44 (0x4446 in little-endian) + - ClockSeqHighAndReserved: 0x83 + - ClockSeqLow: 0x14 + - Node: 0x00, 0xab, 0x93, 0x3c, 0x87, 0xa3 + - Byte representation in memory: + - dc ae 8d 37 6b f0 46 44 83 14 40 ab 93 3c 87 a3 + +*******************************************************************************/ + +/** + This function converts a GUID in UEFI format to a UUID in RFC4122 format. + + The conversion is done by swapping the byte order of the TimeLow, TimeMid, and + TimeHiAndVersion fields, while keeping the ClockSeq and Node fields unchanged. + + @param [in] FromGuid GUID in format to be converted to UUID RFC4122 format. + @param [out] ToUuid Pointer to a GUID structure that will hold the converted + UUID in RFC4122 format. +**/ +VOID +EFIAPI +ConvertGuidToUuid ( + IN GUID *FromGuid, + OUT GUID *ToUuid + ) +{ + ASSERT (ToUuid != NULL); + ASSERT (FromGuid != NULL); + + CopyGuid (ToUuid, FromGuid); + ToUuid->Data1 = SwapBytes32 (ToUuid->Data1); + ToUuid->Data2 = SwapBytes16 (ToUuid->Data2); + ToUuid->Data3 = SwapBytes16 (ToUuid->Data3); +} + +/** + This function converts a UUID in RFC4122 format to a GUID in UEFI format. + + The conversion is done by swapping the byte order of the time_low, time_mid, and + time_hi_and_version fields, while keeping the ClockSeq and Node fields unchanged. + This function is symmetric to ConvertGuidToUuid. + + @param [in] FromUuid UUID in RFC4122 format to be converted to GUID in UEFI format. + @param [out] ToGuid Pointer to a GUID structure that will hold the converted + GUID in UEFI format. +**/ +VOID +EFIAPI +ConvertUuidToGuid ( + IN GUID *FromUuid, + OUT GUID *ToGuid + ) +{ + // The conversion is symmetric, so we can use the same function. + // The only difference is the order of the parameters. + ConvertGuidToUuid ( + FromUuid, + ToGuid + ); +} From 1e9373e67c7a1c2d0b2a339a3efd1ab285ad9cd9 Mon Sep 17 00:00:00 2001 From: Kun Qin Date: Thu, 24 Apr 2025 16:52:52 -0700 Subject: [PATCH 2/3] MdeModulePkg: ArmFfaLib: Support UUID-GUID conversion interfaces This change moves the existing ConvertEfiGuidToUuid function to public interface to support newly defined functions prototypes. This change also adds the `ArmConvertUuidToEfiGuid` function implementation, which is an inverse of the original conversion. Signed-off-by: Kun Qin --- MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.c | 47 +------------------ 1 file changed, 2 insertions(+), 45 deletions(-) diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.c b/MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.c index 1a2d8985e2e4..34234558132e 100644 --- a/MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.c +++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.c @@ -32,49 +32,6 @@ BOOLEAN gFfaSupported; UINT16 gPartId; -/** - Convert EFI_GUID to UUID format. - for example, If there is EFI_GUID named - "378daedc-f06b-4446-8314-40ab933c87a3", - - EFI_GUID is saved in memory like: - dc ae 8d 37 - 6b f0 46 44 - 83 14 40 ab - 93 3c 87 a3 - - However, UUID should be saved like: - 37 8d ae dc - f0 6b 44 46 - 83 14 40 ab - 93 3c 87 a3 - - FF-A and other software components (i.e. linux-kernel) - uses below format. - - @param [in] Guid EFI_GUID - @param [out] Uuid Uuid - -**/ -STATIC -VOID -EFIAPI -ConvertEfiGuidToUuid ( - IN EFI_GUID *Guid, - OUT UINT64 *Uuid - ) -{ - UINT32 *Data32; - UINT16 *Data16; - - CopyGuid ((EFI_GUID *)Uuid, Guid); - Data32 = (UINT32 *)Uuid; - Data32[0] = SwapBytes32 (Data32[0]); - Data16 = (UINT16 *)&Data32[1]; - Data16[0] = SwapBytes16 (Data16[0]); - Data16[1] = SwapBytes16 (Data16[1]); -} - /** Convert EFI_STATUS to FFA return code. @@ -525,7 +482,7 @@ ArmFfaLibPartitionInfoGet ( } if (ServiceGuid != NULL) { - ConvertEfiGuidToUuid (ServiceGuid, Uuid); + ConvertGuidToUuid (ServiceGuid, (GUID *)Uuid); } else { ZeroMem (Uuid, sizeof (Uuid)); } @@ -689,7 +646,7 @@ ArmFfaLibMsgSendDirectReq2 ( } if (ServiceGuid != NULL) { - ConvertEfiGuidToUuid (ServiceGuid, Uuid); + ConvertGuidToUuid (ServiceGuid, (GUID *)Uuid); } else { ZeroMem (Uuid, sizeof (Uuid)); } From 38278e88ed4509d81d9cda8b65cb6db5ee8428bd Mon Sep 17 00:00:00 2001 From: Kun Qin Date: Thu, 24 Apr 2025 17:02:09 -0700 Subject: [PATCH 3/3] ArmPkg: ArmStandaloneMmCoreEntryPoint: Use common UUID conversion routine As new interfaces are made available to support UUID-GUID conversion, this change is made to leverage new interfaces and remove the locally duplicated code. Signed-off-by: Kun Qin --- .../ArmStandaloneMmCoreEntryPoint.c | 48 +------------------ 1 file changed, 1 insertion(+), 47 deletions(-) diff --git a/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.c b/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.c index 7b78834f7d9e..52194832e2ec 100644 --- a/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.c +++ b/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.c @@ -796,52 +796,6 @@ InitializeMiscMmCommunicateBuffer ( CopyGuid (&Buffer->HeaderGuid, ServiceGuid); } -/** - Convert UUID to EFI_GUID format. - for example, If there is EFI_GUID named - "378daedc-f06b-4446-8314-40ab933c87a3", - - EFI_GUID is saved in memory like: - dc ae 8d 37 - 6b f0 46 44 - 83 14 40 ab - 93 3c 87 a3 - - However, UUID should be saved like: - 37 8d ae dc - f0 6b 44 46 - 83 14 40 ab - 93 3c 87 a3 - - FF-A and other software components (i.e. linux-kernel) - uses below format. - - To patch mm-service properly, the passed uuid should be converted to - EFI_GUID format. - - @param [in] Uuid Uuid - @param [out] Guid EFI_GUID - -**/ -STATIC -VOID -EFIAPI -ConvertUuidToEfiGuid ( - IN UINT64 *Uuid, - OUT EFI_GUID *Guid - ) -{ - UINT32 *Data32; - UINT16 *Data16; - - Data32 = (UINT32 *)Uuid; - Data32[0] = SwapBytes32 (Data32[0]); - Data16 = (UINT16 *)&Data32[1]; - Data16[0] = SwapBytes16 (Data16[0]); - Data16[1] = SwapBytes16 (Data16[1]); - CopyGuid (Guid, (EFI_GUID *)Uuid); -} - /** A loop to delegate events from SPMC. DelegatedEventLoop() calls ArmCallSvc() to exit to SPMC. @@ -911,7 +865,7 @@ DelegatedEventLoop ( FfaMsgInfo.DirectMsgVersion = DirectMsgV2; Uuid[0] = EventCompleteSvcArgs->Arg2; Uuid[1] = EventCompleteSvcArgs->Arg3; - ConvertUuidToEfiGuid (Uuid, &ServiceGuid); + ConvertUuidToGuid ((GUID *)Uuid, &ServiceGuid); ServiceType = GetServiceType (&ServiceGuid); } else { Status = EFI_INVALID_PARAMETER;