Collation.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /** @file
  2. Unicode collation routines
  3. Copyright (c) 2021 - 2023 Pedro Falcato All rights reserved.
  4. Copyright (c) 2005 - 2017, Intel Corporation. All rights reserved.
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include <Uefi.h>
  8. #include <Library/DebugLib.h>
  9. #include <Library/UefiLib.h>
  10. #include <Library/UefiBootServicesTableLib.h>
  11. #include <Library/MemoryAllocationLib.h>
  12. #include <Protocol/UnicodeCollation.h>
  13. STATIC EFI_UNICODE_COLLATION_PROTOCOL *gUnicodeCollationInterface = NULL;
  14. /*
  15. * Note: This code is heavily based on FatPkg's Unicode collation, since they seem to know what
  16. * they're doing.
  17. * PS: Maybe all this code could be put in a library? It looks heavily shareable.
  18. **/
  19. /**
  20. Check if unicode collation is initialized
  21. @retval TRUE if Ext4InitialiseUnicodeCollation() was already called successfully
  22. @retval FALSE if Ext4InitialiseUnicodeCollation() was not yet called successfully
  23. **/
  24. STATIC
  25. BOOLEAN
  26. Ext4IsCollationInitialized (
  27. VOID
  28. )
  29. {
  30. return gUnicodeCollationInterface != NULL;
  31. }
  32. /**
  33. Worker function to initialize Unicode Collation support.
  34. It tries to locate Unicode Collation (2) protocol and matches it with current
  35. platform language code.
  36. @param[in] DriverHandle The handle used to open Unicode Collation (2) protocol.
  37. @param[in] ProtocolGuid The pointer to Unicode Collation (2) protocol GUID.
  38. @param[in] VariableName The name of the RFC 4646 or ISO 639-2 language variable.
  39. @param[in] DefaultLanguage The default language in case the RFC 4646 or ISO 639-2 language is absent.
  40. @retval EFI_SUCCESS The Unicode Collation (2) protocol has been successfully located.
  41. @retval Others The Unicode Collation (2) protocol has not been located.
  42. **/
  43. STATIC
  44. EFI_STATUS
  45. Ext4InitialiseUnicodeCollationInternal (
  46. IN EFI_HANDLE DriverHandle,
  47. IN EFI_GUID *ProtocolGuid,
  48. IN CONST CHAR16 *VariableName,
  49. IN CONST CHAR8 *DefaultLanguage
  50. )
  51. {
  52. UINTN NumHandles;
  53. EFI_HANDLE *Handles;
  54. EFI_UNICODE_COLLATION_PROTOCOL *Uci;
  55. BOOLEAN Iso639Language;
  56. CHAR8 *Language;
  57. EFI_STATUS RetStatus;
  58. EFI_STATUS Status;
  59. UINTN Idx;
  60. CHAR8 *BestLanguage;
  61. Iso639Language = (BOOLEAN)(ProtocolGuid == &gEfiUnicodeCollationProtocolGuid);
  62. RetStatus = EFI_UNSUPPORTED;
  63. GetEfiGlobalVariable2 (VariableName, (VOID **)&Language, NULL);
  64. Status = gBS->LocateHandleBuffer (
  65. ByProtocol,
  66. ProtocolGuid,
  67. NULL,
  68. &NumHandles,
  69. &Handles
  70. );
  71. if (EFI_ERROR (Status)) {
  72. return Status;
  73. }
  74. for (Idx = 0; Idx < NumHandles; Idx++) {
  75. Status = gBS->OpenProtocol (
  76. Handles[Idx],
  77. ProtocolGuid,
  78. (VOID **)&Uci,
  79. DriverHandle,
  80. NULL,
  81. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  82. );
  83. if (EFI_ERROR (Status)) {
  84. continue;
  85. }
  86. BestLanguage = GetBestLanguage (
  87. Uci->SupportedLanguages,
  88. Iso639Language,
  89. (Language == NULL) ? "" : Language,
  90. DefaultLanguage,
  91. NULL
  92. );
  93. if (BestLanguage != NULL) {
  94. FreePool (BestLanguage);
  95. gUnicodeCollationInterface = Uci;
  96. RetStatus = EFI_SUCCESS;
  97. break;
  98. }
  99. }
  100. if (Language != NULL) {
  101. FreePool (Language);
  102. }
  103. FreePool (Handles);
  104. return RetStatus;
  105. }
  106. /**
  107. Initialises Unicode collation, which is needed for case-insensitive string comparisons
  108. within the driver (a good example of an application of this is filename comparison).
  109. @param[in] DriverHandle Handle to the driver image.
  110. @retval EFI_SUCCESS Unicode collation was successfully initialised.
  111. @retval !EFI_SUCCESS Failure.
  112. **/
  113. EFI_STATUS
  114. Ext4InitialiseUnicodeCollation (
  115. EFI_HANDLE DriverHandle
  116. )
  117. {
  118. EFI_STATUS Status;
  119. Status = EFI_UNSUPPORTED;
  120. // If already done, just return success.
  121. if (Ext4IsCollationInitialized ()) {
  122. return EFI_SUCCESS;
  123. }
  124. //
  125. // First try to use RFC 4646 Unicode Collation 2 Protocol.
  126. //
  127. Status = Ext4InitialiseUnicodeCollationInternal (
  128. DriverHandle,
  129. &gEfiUnicodeCollation2ProtocolGuid,
  130. L"PlatformLang",
  131. (CONST CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLang)
  132. );
  133. //
  134. // If the attempt to use Unicode Collation 2 Protocol fails, then we fall back
  135. // on the ISO 639-2 Unicode Collation Protocol.
  136. //
  137. if (EFI_ERROR (Status)) {
  138. Status = Ext4InitialiseUnicodeCollationInternal (
  139. DriverHandle,
  140. &gEfiUnicodeCollationProtocolGuid,
  141. L"Lang",
  142. (CONST CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLang)
  143. );
  144. }
  145. return Status;
  146. }
  147. /**
  148. Does a case-insensitive string comparison. Refer to EFI_UNICODE_COLLATION_PROTOCOL's StriColl
  149. for more details.
  150. @param[in] Str1 Pointer to a null terminated string.
  151. @param[in] Str2 Pointer to a null terminated string.
  152. @retval 0 Str1 is equivalent to Str2.
  153. @retval >0 Str1 is lexically greater than Str2.
  154. @retval <0 Str1 is lexically less than Str2.
  155. **/
  156. INTN
  157. Ext4StrCmpInsensitive (
  158. IN CHAR16 *Str1,
  159. IN CHAR16 *Str2
  160. )
  161. {
  162. ASSERT (gUnicodeCollationInterface != NULL);
  163. return gUnicodeCollationInterface->StriColl (gUnicodeCollationInterface, Str1, Str2);
  164. }