All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alan Mackenzie <acm@muc.de>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Jiri Slaby <jirislaby@kernel.org>,
	Simona Vetter <simona@ffwll.ch>,
	linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org,
	Helge Deller <deller@gmx.de>,
	Thomas Zimmermann <tzimmermann@suse.de>,
	linux-fbdev@vger.kernel.org, dri-devel@lists.freedesktop.org
Cc: acm@muc.de
Subject: [Patch 1/9]: Make consolemap.c handle Unicode planes outside BMP
Date: Thu, 27 Aug 2026 18:42:52 +0000	[thread overview]
Message-ID: <apCFLI0ga-DG-HRN@MAC.fritz.box> (raw)
In-Reply-To: <apCEDM2sWv_M354-@MAC.fritz.box>

vt: 32b glyph: 1. Make consolemap.c handle Unicode planes outside BMP

For this, add a fourth layer "planes" onto the sparse map in
this file.  Also handle glyph numbers up to 2^21 rather than
256/512.  Move the conversion between __user and kernel data
from consolemap.c to vt_ioctl.c.

Signed-off-by: Alan Mackenzie <acm@muc.de>

diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c
index 3fa89a2dbeba..2f695d97f0eb 100644
--- a/drivers/tty/vt/consolemap.c
+++ b/drivers/tty/vt/consolemap.c
@@ -34,11 +34,11 @@
 #include <linux/tty.h>
 #include <linux/uaccess.h>
 #include <linux/console.h>
-#include <linux/consolemap.h>
 #include <linux/vt_kern.h>
+#include <linux/consolemap.h>
 #include <linux/string.h>
 
-static unsigned short translations[][E_TABSZ] = {
+static u1632 translations[][E_TABSZ] = {
   /* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
   [LAT1_MAP] = {
     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
@@ -184,66 +184,79 @@ static unsigned short translations[][E_TABSZ] = {
 /* The standard kernel character-to-font mappings are not invertible
    -- this is just a best effort. */
 
-#define MAX_GLYPH 512		/* Max possible glyph value */
+#ifdef CONFIG_FB_GLYPH_21BIT
+#define MAX_GLYPH 0x110000
+#else
+#define MAX_GLYPH 512
+#endif
 
 static enum translation_map inv_translate[MAX_NR_CONSOLES];
 
-#define UNI_DIRS	32U
+#define UNI_PLANES	32U	/* Actually, only 17. */
+#define UNI_PLANE_DIRS	32U
 #define UNI_DIR_ROWS	32U
 #define UNI_ROW_GLYPHS	64U
 
+#define UNI_PLANE_BITS		GENMASK(20, 16)
 #define UNI_DIR_BITS		GENMASK(15, 11)
 #define UNI_ROW_BITS		GENMASK(10,  6)
 #define UNI_GLYPH_BITS		GENMASK( 5,  0)
 
+#ifdef CONFIG_FB_GLYPH_21BIT
+#define UNI_PLANE(uni)		FIELD_GET(UNI_PLANE_BITS, (uni))
+#else
+#define UNI_PLANE(uni)		0
+#endif
 #define UNI_DIR(uni)		FIELD_GET(UNI_DIR_BITS, (uni))
 #define UNI_ROW(uni)		FIELD_GET(UNI_ROW_BITS, (uni))
 #define UNI_GLYPH(uni)		FIELD_GET(UNI_GLYPH_BITS, (uni))
 
-#define UNI(dir, row, glyph)	(FIELD_PREP(UNI_DIR_BITS, (dir)) | \
+#define UNI(plane, dir, row, glyph) (FIELD_PREP(UNI_PLANE_BITS, (plane)) | \
+				 FIELD_PREP(UNI_DIR_BITS, (dir)) | \
 				 FIELD_PREP(UNI_ROW_BITS, (row)) | \
 				 FIELD_PREP(UNI_GLYPH_BITS, (glyph)))
 
 /**
  * struct uni_pagedict - unicode directory
  *
- * @uni_pgdir: 32*32*64 table with glyphs
+ * @uni_plane: 32*32*32*64 table with glyphs
+ * @count: Number of unicode entries in this structure
  * @refcount: reference count of this structure
  * @sum: checksum
  * @inverse_translations: best-effort inverse mapping
  * @inverse_trans_unicode: best-effort inverse mapping to unicode
  */
 struct uni_pagedict {
-	u16		**uni_pgdir[UNI_DIRS];
+	u1632		***uni_plane[UNI_PLANES];
+	u32		count;
 	unsigned long	refcount;
 	unsigned long	sum;
 	unsigned char	*inverse_translations[LAST_MAP + 1];
-	u16		*inverse_trans_unicode;
+	u1632		*inverse_trans_unicode;
 };
 
 static struct uni_pagedict *dflt;
 
 static void set_inverse_transl(struct vc_data *conp, struct uni_pagedict *dict,
-	       enum translation_map m)
+			       enum translation_map m)
 {
-	unsigned short *t = translations[m];
+	u1632 *t = translations[m];
 	unsigned char *inv;
 
 	if (!dict)
 		return;
 	inv = dict->inverse_translations[m];
 
-	if (!inv) {
-		inv = dict->inverse_translations[m] = kmalloc(MAX_GLYPH,
-				GFP_KERNEL);
-		if (!inv)
-			return;
-	}
-	memset(inv, 0, MAX_GLYPH);
+	kfree(inv);
+	inv = dict->inverse_translations[m] =
+		kmalloc(dict->count * (sizeof(*t)), GFP_KERNEL);
+	if (!inv)
+		return;
+	memset(inv, 0, dict->count * (sizeof(*t)));
 
 	for (unsigned int ch = 0; ch < ARRAY_SIZE(translations[m]); ch++) {
 		int glyph = conv_uni_to_pc(conp, t[ch]);
-		if (glyph >= 0 && glyph < MAX_GLYPH && inv[glyph] < 32) {
+		if (glyph >= 0 && glyph < dict->count && inv[glyph] < 32) {
 			/* prefer '-' above SHY etc. */
 			inv[glyph] = ch;
 		}
@@ -252,39 +265,48 @@ static void set_inverse_transl(struct vc_data *conp, struct uni_pagedict *dict,
 
 static void set_inverse_trans_unicode(struct uni_pagedict *dict)
 {
-	unsigned int d, r, g;
-	u16 *inv;
+	unsigned int p, d, r, g;
+	u1632 *inv;
 
 	if (!dict)
 		return;
 
 	inv = dict->inverse_trans_unicode;
-	if (!inv) {
-		inv = dict->inverse_trans_unicode = kmalloc_array(MAX_GLYPH,
-				sizeof(*inv), GFP_KERNEL);
-		if (!inv)
-			return;
-	}
-	memset(inv, 0, MAX_GLYPH * sizeof(*inv));
+	kfree(inv);
+	inv = dict->inverse_trans_unicode =
+		kmalloc_array(dict->count, sizeof(*inv), GFP_KERNEL);
+	if (!inv)
+		return;
+	memset(inv, 0, dict->count * sizeof(*inv));
 
-	for (d = 0; d < UNI_DIRS; d++) {
-		u16 **dir = dict->uni_pgdir[d];
-		if (!dir)
+	for (p = 0; p < UNI_PLANES; p++) {
+		u1632 ***plane = dict->uni_plane[p];
+
+		if (!plane)
 			continue;
-		for (r = 0; r < UNI_DIR_ROWS; r++) {
-			u16 *row = dir[r];
-			if (!row)
+		for (d = 0; d < UNI_PLANE_DIRS; d++) {
+			u1632 **dir = plane[d];
+
+			if (!dir)
 				continue;
-			for (g = 0; g < UNI_ROW_GLYPHS; g++) {
-				u16 glyph = row[g];
-				if (glyph < MAX_GLYPH && inv[glyph] < 32)
-					inv[glyph] = UNI(d, r, g);
+			for (r = 0; r < UNI_DIR_ROWS; r++) {
+				u1632 *row = dir[r];
+
+				if (!row)
+					continue;
+				for (g = 0; g < UNI_ROW_GLYPHS; g++) {
+					u1632 glyph = row[g];
+
+					if (glyph < dict->count &&
+					    inv[glyph] < 32)
+						inv[glyph] = UNI(p, d, r, g);
+				}
 			}
 		}
 	}
 }
 
-unsigned short *set_translate(enum translation_map m, struct vc_data *vc)
+u1632 *set_translate(enum translation_map m, struct vc_data *vc)
 {
 	inv_translate[vc->vc_num] = m;
 	return translations[m];
@@ -297,18 +319,19 @@ unsigned short *set_translate(enum translation_map m, struct vc_data *vc)
  *    was active.
  * Still, it is now possible to a certain extent to cut and paste non-ASCII.
  */
-u16 inverse_translate(const struct vc_data *conp, u16 glyph, bool use_unicode)
+u1632 inverse_translate(const struct vc_data *conp, u1632 glyph,
+			bool use_unicode)
 {
 	struct uni_pagedict *p;
 	enum translation_map m;
 
-	if (glyph >= MAX_GLYPH)
-		return 0;
-
 	p = *conp->uni_pagedict_loc;
 	if (!p)
 		return glyph;
 
+	if (glyph >= p->count)
+		return 0;
+
 	if (use_unicode) {
 		if (!p->inverse_trans_unicode)
 			return glyph;
@@ -371,7 +394,7 @@ int con_set_trans_old(unsigned char __user * arg)
 int con_get_trans_old(unsigned char __user * arg)
 {
 	int i, ch;
-	unsigned short *p = translations[USER_MAP];
+	u1632 *p = translations[USER_MAP];
 	unsigned char outbuf[E_TABSZ];
 
 	scoped_guard(console_lock)
@@ -410,31 +433,38 @@ int con_get_trans_new(ushort __user * arg)
 /*
  * Unicode -> current font conversion
  *
- * A font has at most 512 chars, usually 256.
+ * A font has at most 512 chars (2026-01: no longer true), usually 256.
  * But one font position may represent several Unicode chars.
  * A hashtable is somewhat of a pain to deal with, so use a
  * "paged table" instead.  Simulation has shown the memory cost of
- * this 3-level paged table scheme to be comparable to a hash table.
+ * this 4-level paged table scheme to be comparable to a hash table.
  */
 
-extern u8 dfont_unicount[];	/* Defined in console_defmap.c */
-extern u16 dfont_unitable[];
-
 static void con_release_unimap(struct uni_pagedict *dict)
 {
-	unsigned int d, r;
+	unsigned int p, d, r;
 
 	if (dict == dflt)
 		dflt = NULL;
 
-	for (d = 0; d < UNI_DIRS; d++) {
-		u16 **dir = dict->uni_pgdir[d];
-		if (dir != NULL) {
-			for (r = 0; r < UNI_DIR_ROWS; r++)
-				kfree(dir[r]);
-			kfree(dir);
+	for (p = 0; p < UNI_PLANES; p++) {
+		u1632 ***plane = dict->uni_plane[p];
+
+		if (plane != NULL) {
+			for (d = 0; d < UNI_PLANE_DIRS; d++) {
+				u1632 **dir = plane[d];
+
+				if (dir != NULL) {
+					for (r = 0; r < UNI_DIR_ROWS; r++)
+						if (dir[r] != NULL)
+							kfree(dir[r]);
+					kfree(dir);
+				}
+				plane[d] = NULL;
+			}
+			kfree(plane);
+			dict->uni_plane[p] = NULL;
 		}
-		dict->uni_pgdir[d] = NULL;
 	}
 
 	for (r = 0; r < ARRAY_SIZE(dict->inverse_translations); r++) {
@@ -464,7 +494,7 @@ void con_free_unimap(struct vc_data *vc)
 static int con_unify_unimap(struct vc_data *conp, struct uni_pagedict *dict1)
 {
 	struct uni_pagedict *dict2;
-	unsigned int cons, d, r;
+	unsigned int cons, p, d, r;
 
 	for (cons = 0; cons < MAX_NR_CONSOLES; cons++) {
 		if (!vc_cons_allocated(cons))
@@ -472,26 +502,39 @@ static int con_unify_unimap(struct vc_data *conp, struct uni_pagedict *dict1)
 		dict2 = *vc_cons[cons].d->uni_pagedict_loc;
 		if (!dict2 || dict2 == dict1 || dict2->sum != dict1->sum)
 			continue;
-		for (d = 0; d < UNI_DIRS; d++) {
-			u16 **dir1 = dict1->uni_pgdir[d];
-			u16 **dir2 = dict2->uni_pgdir[d];
-			if (!dir1 && !dir2)
+		for (p = 0; p < UNI_PLANES; p++) {
+			u1632 ***plane1 = dict1->uni_plane[p];
+			u1632 ***plane2 = dict2->uni_plane[p];
+
+			if (!plane1 && !plane2)
 				continue;
-			if (!dir1 || !dir2)
+			if (!plane1 || !plane2)
 				break;
-			for (r = 0; r < UNI_DIR_ROWS; r++) {
-				if (!dir1[r] && !dir2[r])
+			for (d = 0; d < UNI_PLANE_DIRS; d++) {
+				u1632 **dir1 = plane1[d];
+				u1632 **dir2 = plane2[d];
+
+				if (!dir1 && !dir2)
 					continue;
-				if (!dir1[r] || !dir2[r])
+				if (!dir1 || !dir2)
 					break;
-				if (memcmp(dir1[r], dir2[r], UNI_ROW_GLYPHS *
-							sizeof(*dir1[r])))
+				for (r = 0; r < UNI_DIR_ROWS; r++) {
+					if (!dir1[r] && !dir2[r])
+						continue;
+					if (!dir1[r] || !dir2[r])
+						break;
+					if (memcmp(dir1[r], dir2[r],
+						   UNI_ROW_GLYPHS *
+						   sizeof(*dir1[r])))
+						break;
+				}
+				if (r < UNI_DIR_ROWS)
 					break;
 			}
-			if (r < UNI_DIR_ROWS)
+			if (d < UNI_PLANE_DIRS)
 				break;
 		}
-		if (d == UNI_DIRS) {
+		if (p == UNI_PLANES) {
 			dict2->refcount++;
 			*conp->uni_pagedict_loc = dict2;
 			con_release_unimap(dict1);
@@ -503,15 +546,24 @@ static int con_unify_unimap(struct vc_data *conp, struct uni_pagedict *dict1)
 }
 
 static int
-con_insert_unipair(struct uni_pagedict *p, u_short unicode, u_short fontpos)
+con_insert_unipair(struct uni_pagedict *p, u1632 unicode, u1632 fontpos)
 {
-	u16 **dir, *row;
+	u1632 ***plane, **dir, *row;
 	unsigned int n;
 
+	n = UNI_PLANE(unicode);
+	plane = p->uni_plane[n];
+	if (!plane) {
+		plane = p->uni_plane[n] = kcalloc
+			(UNI_PLANE_DIRS, sizeof(*plane), GFP_KERNEL);
+		if (!plane)
+			return -ENOMEM;
+	}
+
 	n = UNI_DIR(unicode);
-	dir = p->uni_pgdir[n];
+	dir = plane[n];
 	if (!dir) {
-		dir = p->uni_pgdir[n] = kcalloc(UNI_DIR_ROWS, sizeof(*dir),
+		dir = plane[n] = kcalloc(UNI_DIR_ROWS, sizeof(*dir),
 				GFP_KERNEL);
 		if (!dir)
 			return -ENOMEM;
@@ -573,12 +625,12 @@ int con_clear_unimap(struct vc_data *vc)
 }
 
 static struct uni_pagedict *con_unshare_unimap(struct vc_data *vc,
-		struct uni_pagedict *old)
+					       struct uni_pagedict *old)
 {
 	struct uni_pagedict *new;
-	unsigned int d, r, g;
+	unsigned int p, d, r, g;
 	int ret;
-	u16 uni = 0;
+	u32 uni = 0;
 
 	ret = con_allocate_new(vc);
 	if (ret)
@@ -587,63 +639,70 @@ static struct uni_pagedict *con_unshare_unimap(struct vc_data *vc,
 	new = *vc->uni_pagedict_loc;
 
 	/*
-	 * uni_pgdir is a 32*32*64 table with rows allocated when its first
+	 * uni_plane is a 32*32*32*64 table with a row allocated when its first
 	 * entry is added. The unicode value must still be incremented for
 	 * empty rows. We are copying entries from "old" to "new".
 	 */
-	for (d = 0; d < UNI_DIRS; d++) {
-		u16 **dir = old->uni_pgdir[d];
-		if (!dir) {
+	for (p = 0; p < UNI_PLANES; p++) {
+		u1632 ***plane = old->uni_plane[p];
+
+		if (!plane) {
 			/* Account for empty table */
-			uni += UNI_DIR_ROWS * UNI_ROW_GLYPHS;
+			uni += UNI_PLANE_DIRS * UNI_DIR_ROWS * UNI_ROW_GLYPHS;
 			continue;
 		}
 
-		for (r = 0; r < UNI_DIR_ROWS; r++) {
-			u16 *row = dir[r];
-			if (!row) {
-				/* Account for row of 64 empty entries */
-				uni += UNI_ROW_GLYPHS;
+		for (d = 0; d < UNI_PLANE_DIRS; d++) {
+			u1632 **dir = plane[d];
+
+			if (!dir) {
+				/* Account for empty table */
+				uni += UNI_DIR_ROWS * UNI_ROW_GLYPHS;
 				continue;
 			}
 
-			for (g = 0; g < UNI_ROW_GLYPHS; g++, uni++) {
-				if (row[g] == 0xffff)
+			for (r = 0; r < UNI_DIR_ROWS; r++) {
+				u1632 *row = dir[r];
+
+				if (!row) {
+					/* Account for row of 64 empty entries */
+					uni += UNI_ROW_GLYPHS;
 					continue;
-				/*
-				 * Found one, copy entry for unicode uni with
-				 * fontpos value row[g].
-				 */
-				ret = con_insert_unipair(new, uni, row[g]);
-				if (ret) {
-					old->refcount++;
-					*vc->uni_pagedict_loc = old;
-					con_release_unimap(new);
-					kfree(new);
-					return ERR_PTR(ret);
+				}
+
+				for (g = 0; g < UNI_ROW_GLYPHS; g++, uni++) {
+					if (row[g] == ~0)
+						continue;
+					/*
+					 * Found one, copy entry for unicode
+					 * uni with fontpos value row[g].
+					 */
+					ret = con_insert_unipair(new, uni,
+								 row[g]);
+					if (ret) {
+						old->refcount++;
+						*vc->uni_pagedict_loc = old;
+						con_release_unimap(new);
+						kfree(new);
+						return ERR_PTR(ret);
+					}
 				}
 			}
 		}
 	}
-
 	return new;
 }
 
-int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
+int con_set_unimap(struct vc_data *vc, u32 ct, struct unipair8_21 *list)
 {
-	struct uni_pagedict *dict;
-	struct unipair *plist;
 	int err = 0;
+	struct uni_pagedict *dict;
+	struct unipair8_21 *plist;
 
 	if (!ct)
 		return 0;
 
-	struct unipair *unilist __free(kvfree) = vmemdup_array_user(list, ct, sizeof(*unilist));
-	if (IS_ERR(unilist))
-		return PTR_ERR(unilist);
-
 	guard(console_lock)();
-
 	/* Save original vc_unipagdir_loc in case we allocate a new one */
 	dict = *vc->uni_pagedict_loc;
 	if (!dict)
@@ -660,7 +719,9 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
 	/*
 	 * Insert user specified unicode pairs into new table.
 	 */
-	for (plist = unilist; ct; ct--, plist++) {
+	err = 0;
+	dict->count = ct;
+	for (plist = list; ct; ct--, plist++) {
 		int err1 = con_insert_unipair(dict, plist->unicode, plist->fontpos);
 		if (err1)
 			err = err1;
@@ -769,54 +830,69 @@ EXPORT_SYMBOL(con_copy_unimap);
  *	Read the console unicode data for this console. Called from the ioctl
  *	handlers.
  */
-int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct,
-		struct unipair __user *list)
+int con_get_unimap(struct vc_data *vc, u32 ct, u1632 *uct,
+		   struct unipair8_21 *list)
 {
-	ushort ect;
+	u1632 ect;
 	struct uni_pagedict *dict;
-	unsigned int d, r, g;
+	unsigned int p, d, r, g;
+	int ret = 0;
 
-	struct unipair *unilist __free(kvfree) = kvmalloc_array(ct, sizeof(*unilist), GFP_KERNEL);
-	if (!unilist)
-		return -ENOMEM;
+	scoped_guard (console_lock) {
 
-	scoped_guard(console_lock) {
 		ect = 0;
 		dict = *vc->uni_pagedict_loc;
 		if (!dict)
 			break;
 
-		for (d = 0; d < UNI_DIRS; d++) {
-			u16 **dir = dict->uni_pgdir[d];
-			if (!dir)
+		for (p = 0; p < UNI_PLANES; p++) {
+			u1632 ***plane = dict->uni_plane[p];
+
+			if (!plane)
 				continue;
 
-			for (r = 0; r < UNI_DIR_ROWS; r++) {
-				u16 *row = dir[r];
-				if (!row)
+			for (d = 0; d < UNI_PLANE_DIRS; d++) {
+				u1632 **dir = plane[d];
+
+				if (!dir)
 					continue;
 
-				for (g = 0; g < UNI_ROW_GLYPHS; g++, row++) {
-					if (*row >= MAX_GLYPH)
+				for (r = 0; r < UNI_DIR_ROWS; r++) {
+					u1632 *row = dir[r];
+
+					if (!row)
 						continue;
-					if (ect < ct) {
-						unilist[ect].unicode = UNI(d, r, g);
-						unilist[ect].fontpos = *row;
+
+					for (g = 0; g < UNI_ROW_GLYPHS; g++, row++) {
+						if (*row >= dict->count)
+							continue;
+						if (ect < ct) {
+#ifndef CONFIG_FB_GLYPH_21BIT
+							if ((p || *row > 0xffff)) {
+								ret = -EINVAL;
+								goto unlock;
+							}
+#endif
+							if (list) {
+								list[ect].unicode = UNI(p, d, r, g);
+								list[ect].fontpos = *row;
+							}
+						}
+						ect++;
 					}
-					ect++;
 				}
 			}
 		}
+#ifndef CONFIG_FB_GLYPH_21BIT
+unlock:
+#endif
 	}
-
-	if (copy_to_user(list, unilist, min(ect, ct) * sizeof(*unilist)))
-		return -EFAULT;
-	if (put_user(ect, uct))
-		return -EFAULT;
-	if (ect > ct)
-		return -ENOMEM;
-
-	return 0;
+	*uct = ect;
+	/* NOTE: For the correct functioning of the program setfont, it is
+	 * critical that -ENOMEM, not 0, is returned when ct is zero.  ACM,
+	 * 2025-02-12.
+	 */
+	return ret ? ret : (ect <= ct) ? 0 : -ENOMEM;
 }
 
 /*
@@ -849,26 +925,33 @@ int conv_uni_to_8bit(u32 uni)
 int conv_uni_to_pc(struct vc_data *conp, long ucs)
 {
 	struct uni_pagedict *dict;
-	u16 **dir, *row, glyph;
+	u1632 ***plane, **dir, *row, glyph;
 
-	/* Only 16-bit codes supported at this time */
-	if (ucs > 0xffff)
-		return -4;		/* Not found */
+	if (ucs >= MAX_GLYPH)
+		return -4;	/* Not found */
 	else if (ucs < 0x20)
 		return -1;		/* Not a printable character */
+	else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
+		return -2;			/* Zero-width space */
 	/*
 	 * UNI_DIRECT_BASE indicates the start of the region in the User Zone
 	 * which always has a 1:1 mapping to the currently loaded font.  The
 	 * UNI_DIRECT_MASK indicates the bit span of the region.
 	 */
+#ifndef CONFIG_FB_GLYPH_21BIT
 	else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
 		return ucs & UNI_DIRECT_MASK;
+#endif
 
 	dict = *conp->uni_pagedict_loc;
 	if (!dict)
 		return -3;
 
-	dir = dict->uni_pgdir[UNI_DIR(ucs)];
+	plane = dict->uni_plane[UNI_PLANE(ucs)];
+	if (!plane)
+		return -4;
+
+	dir = plane[UNI_DIR(ucs)];
 	if (!dir)
 		return -4;
 
@@ -897,4 +980,3 @@ console_map_init(void)
 		if (vc_cons_allocated(i) && !*vc_cons[i].d->uni_pagedict_loc)
 			con_set_default_unimap(vc_cons[i].d);
 }
-

-- 
Alan Mackenzie (Nuremberg, Germany).

  reply	other threads:[~2026-08-27 18:42 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-27 18:38 vt: Enlarge the framebuffer glyph size from 16 to 32 bits Alan Mackenzie
2026-08-27 18:42 ` Alan Mackenzie [this message]
2026-08-27 19:14   ` [Patch 1/9]: Make consolemap.c handle Unicode planes outside BMP sashiko-bot
2026-08-28  4:57   ` Jiri Slaby
2026-08-29 11:51     ` Alan Mackenzie
2026-08-27 18:45 ` [Patch 2/9]: Glyph size: Use GLYPH_SZ/HW rather than hardcoded 2, 1 Alan Mackenzie
2026-08-27 19:22   ` sashiko-bot
2026-08-27 18:47 ` [Patch 3/9]: Replace scr_readw/writew by scr_readg/writeg, etc Alan Mackenzie
2026-08-27 19:18   ` sashiko-bot
2026-08-29 12:11   ` Greg Kroah-Hartman
2026-08-29 13:33     ` Alan Mackenzie
2026-08-27 18:48 ` [Patch 4/9]: Amend internal manipulation of glyph structure Alan Mackenzie
2026-08-27 19:19   ` sashiko-bot
2026-08-27 18:50 ` [Patch 5/9]: vt: Amend three Kconfig files Alan Mackenzie
2026-08-27 19:12   ` sashiko-bot
2026-08-27 18:52 ` [Patch 6/9]: vt: Use u32 and typedef u1632 to handle whole glyphs Alan Mackenzie
2026-08-27 19:22   ` sashiko-bot
2026-08-27 18:54 ` [Patch 7/9]: vt: Handle up to 2^21 glyphs, rather than 256/512 Alan Mackenzie
2026-08-27 19:14   ` sashiko-bot
2026-08-27 18:56 ` [Patch 8/9]: vt: Enhancements to the VT ioctl interface Alan Mackenzie
2026-08-27 19:25   ` sashiko-bot
2026-08-27 18:58 ` [Patch 9/9]: vt: Misc changes, e.g. to #include directives Alan Mackenzie
2026-08-27 19:25   ` sashiko-bot
2026-08-29 12:06   ` Greg Kroah-Hartman
2026-08-28  6:12 ` vt: Enlarge the framebuffer glyph size from 16 to 32 bits Thomas Zimmermann
2026-08-28 14:36   ` Alan Mackenzie
2026-08-29 12:09     ` Greg Kroah-Hartman
2026-08-29 14:39       ` Alan Mackenzie
2026-08-31  6:20         ` Thomas Zimmermann
2026-08-31 14:45           ` Alan Mackenzie
2026-08-31 17:21             ` Helge Deller
2026-09-01 11:14               ` Alan Mackenzie

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=apCFLI0ga-DG-HRN@MAC.fritz.box \
    --to=acm@muc.de \
    --cc=deller@gmx.de \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=jirislaby@kernel.org \
    --cc=linux-fbdev@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    --cc=simona@ffwll.ch \
    --cc=tzimmermann@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.