Not complete, but enough for Shell.efi and SCT.efi. Signed-off-by: Rob Clark <robdcl...@gmail.com> --- include/efi_api.h | 9 +++ include/efi_loader.h | 1 + lib/efi_loader/efi_boottime.c | 5 +- lib/efi_loader/efi_unicode.c | 143 +++++++++++++++++++++++++++++++++++------- 4 files changed, 134 insertions(+), 24 deletions(-)
diff --git a/include/efi_api.h b/include/efi_api.h index 4853b71497..5612dfad49 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -804,6 +804,15 @@ struct efi_hii_string_protocol UINTN *secondary_languages_size); }; +/* + * Both UNICODE_COLLATION protocols seem to be the same thing, but + * advertised with two different GUID's because, why not? + */ + +#define EFI_UNICODE_COLLATION_PROTOCOL_GUID \ + EFI_GUID(0x1d85cd7f, 0xf43d, 0x11d2, \ + 0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + #define EFI_UNICODE_COLLATION_PROTOCOL2_GUID \ EFI_GUID(0xa4c751fc, 0x23ae, 0x4c3e, \ 0x92, 0xe9, 0x49, 0x64, 0xcf, 0x63, 0xf3, 0x49) diff --git a/include/efi_loader.h b/include/efi_loader.h index 6668338d0b..4864b3ac77 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -77,6 +77,7 @@ extern const efi_guid_t efi_guid_device_path_utilities_protocol; extern const efi_guid_t efi_guid_hii_config_routing_protocol; extern const efi_guid_t efi_guid_hii_database_protocol; extern const efi_guid_t efi_guid_hii_string_protocol; +extern const efi_guid_t efi_guid_unicode_collation_protocol; extern const efi_guid_t efi_guid_unicode_collation_protocol2; extern unsigned int __efi_runtime_start, __efi_runtime_stop; diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 04358e8aca..7b53570354 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -788,9 +788,12 @@ void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *ob obj->protocols[7].guid = &efi_guid_hii_config_routing_protocol; obj->protocols[7].protocol_interface = (void *)&efi_hii_config_routing; - obj->protocols[8].guid = &efi_guid_unicode_collation_protocol2; + obj->protocols[8].guid = &efi_guid_unicode_collation_protocol; obj->protocols[8].protocol_interface = (void *)&efi_unicode_collation; + obj->protocols[9].guid = &efi_guid_unicode_collation_protocol2; + obj->protocols[9].protocol_interface = (void *)&efi_unicode_collation; + info->file_path = file_path; info->device_handle = efi_dp_find_obj(device_path, NULL); diff --git a/lib/efi_loader/efi_unicode.c b/lib/efi_loader/efi_unicode.c index fdf1a99812..8d8edfb45a 100644 --- a/lib/efi_loader/efi_unicode.c +++ b/lib/efi_loader/efi_unicode.c @@ -7,59 +7,155 @@ */ #include <common.h> +#include <charset.h> +#include <linux/ctype.h> #include <efi_loader.h> +const efi_guid_t efi_guid_unicode_collation_protocol = + EFI_UNICODE_COLLATION_PROTOCOL_GUID; + const efi_guid_t efi_guid_unicode_collation_protocol2 = EFI_UNICODE_COLLATION_PROTOCOL2_GUID; -INTN stri_coll(struct efi_unicode_collation_protocol *this, - efi_string_t s1, - efi_string_t s2) +static int matchn(efi_string_t s1, unsigned n1, efi_string_t s2, unsigned n2) +{ + char u1[MAX_UTF8_PER_UTF16 * n1 + 1]; + char u2[MAX_UTF8_PER_UTF16 * n2 + 1]; + + *utf16_to_utf8((u8 *)u1, s1, n1) = '\0'; + *utf16_to_utf8((u8 *)u2, s2, n2) = '\0'; + + return strcasecmp(u1, u2); +} + +static INTN EFIAPI stri_coll(struct efi_unicode_collation_protocol *this, + efi_string_t s1, + efi_string_t s2) { EFI_ENTRY("%p, \"%ls\", \"%ls\"", this, s1, s2); - return EFI_EXIT(0); + + unsigned n1 = utf16_strlen(s1); + unsigned n2 = utf16_strlen(s2); + + return EFI_EXIT(matchn(s1, n1, s2, n2)); } -bool metai_match(struct efi_unicode_collation_protocol *this, - efi_string_t string, - efi_string_t pattern) +static bool match(efi_string_t string, efi_string_t pattern) +{ + while (true) { + uint16_t p = *pattern++; + bool matches = false; + + if (p == '\0' || *string == '\0') { + /* + * End of pattern or string, succeed if + * end of both: + */ + return *string == p; + } + + switch (p) { + case '*': + /* Match zero or more chars: */ + while (*string != '\0') { + if (match(string, pattern)) + return true; + string++; + } + return match(string, pattern); + case '?': + /* Match any one char: */ + string++; + break; + case '[': + /* Match char set, either [abc] or [a-c]: */ + + if (pattern[0] == '\0' || pattern[0] == ']') { + /* invalid pattern */ + return false; + } + + if (pattern[1] == '-') { + uint16_t lo, hi, c; + + /* range: [a-c] */ + lo = pattern[0]; + hi = pattern[2]; + + if (hi == '\0' || hi == ']' || pattern[3] != ']') { + /* invalid pattern */ + return false; + } + + c = tolower(*string); + lo = tolower(lo); + hi = tolower(hi); + + if (lo <= c && c <= hi) + matches = true; + + pattern += 4; + } else { + /* set: [abc] */ + while ((p = *pattern++) && p != ']') + if (matchn(string, 1, &p, 1)) + matches = true; + } + + if (!matches) + return false; + + string++; + break; + default: + if (matchn(string, 1, &p, 1)) + return false; + string++; + break; + } + } +} + +static bool EFIAPI metai_match(struct efi_unicode_collation_protocol *this, + efi_string_t string, + efi_string_t pattern) { EFI_ENTRY("%p, \"%ls\", \"%ls\"", this, string, pattern); - return EFI_EXIT(false); + return EFI_EXIT(match(string, pattern)); } -void str_lwr(struct efi_unicode_collation_protocol *this, - efi_string_t string) +static void EFIAPI str_lwr(struct efi_unicode_collation_protocol *this, + efi_string_t string) { EFI_ENTRY("%p, \"%ls\"", this, string); EFI_EXIT(0); return; } -void str_upr(struct efi_unicode_collation_protocol *this, - efi_string_t string) +static void EFIAPI str_upr(struct efi_unicode_collation_protocol *this, + efi_string_t string) { EFI_ENTRY("%p, \"%ls\"", this, string); EFI_EXIT(0); return; } -void fat_to_str(struct efi_unicode_collation_protocol *this, - UINTN fat_size, - uint8_t *fat, - efi_string_t string) +static void EFIAPI fat_to_str(struct efi_unicode_collation_protocol *this, + UINTN fat_size, + uint8_t *fat, + efi_string_t string) { - EFI_ENTRY("%p, %lu, \"%s\", %p", this, fat_size, fat, string); + EFI_ENTRY("%p, %zu, \"%s\", %p", this, fat_size, fat, string); EFI_EXIT(0); return; } -bool str_to_fat(struct efi_unicode_collation_protocol *this, - efi_string_t string, - UINTN fat_size, - uint8_t *fat) +static bool EFIAPI str_to_fat(struct efi_unicode_collation_protocol *this, + efi_string_t string, + UINTN fat_size, + uint8_t *fat) { - EFI_ENTRY("%p, \"%ls\", %lu, %p", this, string, fat_size, fat); + EFI_ENTRY("%p, \"%ls\", %zu, %p", this, string, fat_size, fat); return EFI_EXIT(false); } @@ -69,5 +165,6 @@ const struct efi_unicode_collation_protocol efi_unicode_collation = { .str_lwr = str_lwr, .str_upr = str_upr, .fat_to_str = fat_to_str, - .str_to_fat = str_to_fat + .str_to_fat = str_to_fat, + .supported_languages = (uint8_t *)"eng", }; -- 2.13.5 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot