// SPDX-License-Identifier: GPL-2.0+
/*
 * EFI Unicode collation protocol
 *
 * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
 */

#include <charset.h>
#include <cp1250.h>
#include <cp437.h>
#include <efi_loader.h>

/* Characters that may not be used in FAT 8.3 file names */
static const char illegal[] = "+,<=>:;\"/\\|?*[]\x7f";

/*
 * EDK2 assumes codepage 1250 when creating FAT 8.3 file names.
 * Linux defaults to codepage 437 for FAT 8.3 file names.
 */
#if CONFIG_FAT_DEFAULT_CODEPAGE == 1250
/* Unicode code points for code page 1250 characters 0x80 - 0xff */
static const u16 codepage[] = CP1250;
#else
/* Unicode code points for code page 437 characters 0x80 - 0xff */
static const u16 *codepage = codepage_437;
#endif

/* GUID of the EFI_UNICODE_COLLATION_PROTOCOL2 */
const efi_guid_t efi_guid_unicode_collation_protocol2 =
	EFI_UNICODE_COLLATION_PROTOCOL2_GUID;

/**
 * efi_stri_coll() - compare utf-16 strings case-insenitively
 *
 * @this:	unicode collation protocol instance
 * @s1:		first string
 * @s2:		second string
 *
 * This function implements the StriColl() service of the
 * EFI_UNICODE_COLLATION_PROTOCOL2.
 *
 * See the Unified Extensible Firmware Interface (UEFI) specification for
 * details.
 *
 * Return:	0: s1 == s2, > 0: s1 > s2, < 0: s1 < s2
 */
static efi_intn_t EFIAPI efi_stri_coll(
		struct efi_unicode_collation_protocol *this, u16 *s1, u16 *s2)
{
	s32 c1, c2;
	efi_intn_t ret = 0;

	EFI_ENTRY("%p, %ls, %ls", this, s1, s2);
	for (; *s1 | *s2; ++s1, ++s2) {
		c1 = utf_to_upper(*s1);
		c2 = utf_to_upper(*s2);
		if (c1 < c2) {
			ret = -1;
			goto out;
		} else if (c1 > c2) {
			ret = 1;
			goto out;
		}
	}
out:
	EFI_EXIT(EFI_SUCCESS);
	return ret;
}

/**
 * next_lower() - get next codepoint converted to lower case
 *
 * @string:	pointer to u16 string, on return advanced by one codepoint
 * Return:	first codepoint of string converted to lower case
 */
static s32 next_lower(const u16 **string)
{
	return utf_to_lower(utf16_get(string));
}

/**
 * metai_match() - compare utf-16 string with a pattern string case-insenitively
 *
 * @string:	string to compare
 * @pattern:	pattern string
 *
 * The pattern string may use these:
 *	- * matches >= 0 characters
 *	- ? matches 1 character
 *	- [<char1><char2>...<charN>] match any character in the set
 *	- [<char1>-<char2>] matches any character in the range
 *
 * This function is called my efi_metai_match().
 *
 * For '*' pattern searches this function calls itself recursively.
 * Performance-wise this is suboptimal, especially for multiple '*' wildcards.
 * But it results in simple code.
 *
 * Return:	true if the string is matched.
 */
static bool metai_match(const u16 *string, const u16 *pattern)
{
	s32 first, s, p;

	for (; *string && *pattern;) {
		const u16 *string_old = string;

		s = next_lower(&string);
		p = next_lower(&pattern);

		switch (p) {
		case '*':
			/* Match 0 or more characters */
			for (;; s = next_lower(&string)) {
				if (metai_match(string_old, pattern))
					return true;
				if (!s)
					return false;
				string_old = string;
			}
		case '?':
			/* Match any one character */
			break;
		case '[':
			/* Match any character in the set */
			p = next_lower(&pattern);
			first = p;
			if (first == ']')
				/* Empty set */
				return false;
			p = next_lower(&pattern);
			if (p == '-') {
				/* Range */
				p = next_lower(&pattern);
				if (s < first || s > p)
					return false;
				p = next_lower(&pattern);
				if (p != ']')
					return false;
			} else {
				/* Set */
				bool hit = false;

				if (s == first)
					hit = true;
				for (; p && p != ']';
				     p = next_lower(&pattern)) {
					if (p == s)
						hit = true;
				}
				if (!hit || p != ']')
					return false;
			}
			break;
		default:
			/* Match one character */
			if (p != s)
				return false;
		}
	}
	if (!*pattern && !*string)
		return true;
	return false;
}

/**
 * efi_metai_match() - compare utf-16 string with a pattern string
 *		       case-insenitively
 *
 * @this:	unicode collation protocol instance
 * @string:	string to compare
 * @pattern:	pattern string
 *
 * The pattern string may use these:
 *	- * matches >= 0 characters
 *	- ? matches 1 character
 *	- [<char1><char2>...<charN>] match any character in the set
 *	- [<char1>-<char2>] matches any character in the range
 *
 * This function implements the MetaMatch() service of the
 * EFI_UNICODE_COLLATION_PROTOCOL2.
 *
 * Return:	true if the string is matched.
 */
static bool EFIAPI efi_metai_match(struct efi_unicode_collation_protocol *this,
				   const u16 *string, const u16 *pattern)
{
	bool ret;

	EFI_ENTRY("%p, %ls, %ls", this, string, pattern);
	ret =  metai_match(string, pattern);
	EFI_EXIT(EFI_SUCCESS);
	return ret;
}

/**
 * efi_str_lwr() - convert to lower case
 *
 * @this:	unicode collation protocol instance
 * @string:	string to convert
 *
 * The conversion is done in place. As long as upper and lower letters use the
 * same number of words this does not pose a problem.
 *
 * This function implements the StrLwr() service of the
 * EFI_UNICODE_COLLATION_PROTOCOL2.
 */
static void EFIAPI efi_str_lwr(struct efi_unicode_collation_protocol *this,
			       u16 *string)
{
	EFI_ENTRY("%p, %ls", this, string);
	for (; *string; ++string)
		*string = utf_to_lower(*string);
	EFI_EXIT(EFI_SUCCESS);
}

/**
 * efi_str_upr() - convert to upper case
 *
 * @this:	unicode collation protocol instance
 * @string:	string to convert
 *
 * The conversion is done in place. As long as upper and lower letters use the
 * same number of words this does not pose a problem.
 *
 * This function implements the StrUpr() service of the
 * EFI_UNICODE_COLLATION_PROTOCOL2.
 */
static void EFIAPI efi_str_upr(struct efi_unicode_collation_protocol *this,
			       u16 *string)
{
	EFI_ENTRY("%p, %ls", this, string);
	for (; *string; ++string)
		*string = utf_to_upper(*string);
	EFI_EXIT(EFI_SUCCESS);
}

/**
 * efi_fat_to_str() - convert an 8.3 file name from an OEM codepage to Unicode
 *
 * @this:	unicode collation protocol instance
 * @fat_size:	size of the string to convert
 * @fat:	string to convert
 * @string:	converted string
 *
 * This function implements the FatToStr() service of the
 * EFI_UNICODE_COLLATION_PROTOCOL2.
 */
static void EFIAPI efi_fat_to_str(struct efi_unicode_collation_protocol *this,
				  efi_uintn_t fat_size, char *fat, u16 *string)
{
	efi_uintn_t i;
	u16 c;

	EFI_ENTRY("%p, %zu, %s, %p", this, fat_size, fat, string);
	for (i = 0; i < fat_size; ++i) {
		c = (unsigned char)fat[i];
		if (c > 0x80)
			c = codepage[c - 0x60];
		string[i] = c;
		if (!c)
			break;
	}
	string[i] = 0;
	EFI_EXIT(EFI_SUCCESS);
}

/**
 * efi_fat_to_str() - convert a utf-16 string to legal characters for a FAT
 *                    file name in an OEM code page
 *
 * @this:	unicode collation protocol instance
 * @string:	Unicode string to convert
 * @fat_size:	size of the target buffer
 * @fat:	converted string
 *
 * This function implements the StrToFat() service of the
 * EFI_UNICODE_COLLATION_PROTOCOL2.
 *
 * Return:	true if an illegal character was substituted by '_'.
 */
static bool EFIAPI efi_str_to_fat(struct efi_unicode_collation_protocol *this,
				  const u16 *string, efi_uintn_t fat_size,
				  char *fat)
{
	efi_uintn_t i;
	s32 c;
	bool ret = false;

	EFI_ENTRY("%p, %ls, %zu, %p", this, string, fat_size, fat);
	for (i = 0; i < fat_size;) {
		c = utf16_get(&string);
		switch (c) {
		/* Ignore period and space */
		case '.':
		case ' ':
			continue;
		case 0:
			break;
		}
		c = utf_to_upper(c);
		if (utf_to_cp(&c, codepage) ||
		    (c && (c < 0x20 || strchr(illegal, c)))) {
			ret = true;
			c = '_';
		}

		fat[i] = c;
		if (!c)
			break;
		++i;
	}
	EFI_EXIT(EFI_SUCCESS);
	return ret;
}

const struct efi_unicode_collation_protocol efi_unicode_collation_protocol2 = {
	.stri_coll = efi_stri_coll,
	.metai_match = efi_metai_match,
	.str_lwr = efi_str_lwr,
	.str_upr = efi_str_upr,
	.fat_to_str = efi_fat_to_str,
	.str_to_fat = efi_str_to_fat,
	.supported_languages = "en",
};
