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