xref: /openbmc/linux/drivers/tty/vt/consolemap.c (revision 2a9c56cc)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * consolemap.c
4  *
5  * Mapping from internal code (such as Latin-1 or Unicode or IBM PC code)
6  * to font positions.
7  *
8  * aeb, 950210
9  *
10  * Support for multiple unimaps by Jakub Jelinek <jj@ultra.linux.cz>, July 1998
11  *
12  * Fix bug in inverse translation. Stanislav Voronyi <stas@cnti.uanet.kharkov.ua>, Dec 1998
13  *
14  * In order to prevent the following circular lock dependency:
15  *   &mm->mmap_lock --> cpu_hotplug.lock --> console_lock --> &mm->mmap_lock
16  *
17  * We cannot allow page fault to happen while holding the console_lock.
18  * Therefore, all the userspace copy operations have to be done outside
19  * the console_lock critical sections.
20  *
21  * As all the affected functions are all called directly from vt_ioctl(), we
22  * can allocate some small buffers directly on stack without worrying about
23  * stack overflow.
24  */
25 
26 #include <linux/bitfield.h>
27 #include <linux/bits.h>
28 #include <linux/module.h>
29 #include <linux/kd.h>
30 #include <linux/errno.h>
31 #include <linux/mm.h>
32 #include <linux/slab.h>
33 #include <linux/init.h>
34 #include <linux/tty.h>
35 #include <linux/uaccess.h>
36 #include <linux/console.h>
37 #include <linux/consolemap.h>
38 #include <linux/vt_kern.h>
39 #include <linux/string.h>
40 
41 static unsigned short translations[][E_TABSZ] = {
42   /* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
43   [LAT1_MAP] = {
44     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
45     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
46     0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
47     0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
48     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
49     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
50     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
51     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
52     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
53     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
54     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
55     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
56     0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
57     0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
58     0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
59     0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
60     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
61     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
62     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
63     0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
64     0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
65     0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
66     0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
67     0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
68     0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
69     0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
70     0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
71     0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
72     0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
73     0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
74     0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
75     0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
76   },
77   /* VT100 graphics mapped to Unicode */
78   [GRAF_MAP] = {
79     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
80     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
81     0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
82     0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
83     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
84     0x0028, 0x0029, 0x002a, 0x2192, 0x2190, 0x2191, 0x2193, 0x002f,
85     0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
86     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
87     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
88     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
89     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
90     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
91     0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
92     0x2591, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
93     0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
94     0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
95     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
96     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
97     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
98     0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
99     0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
100     0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
101     0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
102     0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
103     0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
104     0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
105     0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
106     0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
107     0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
108     0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
109     0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
110     0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
111   },
112   /* IBM Codepage 437 mapped to Unicode */
113   [IBMPC_MAP] = {
114     0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
115     0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
116     0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
117     0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
118     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
119     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
120     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
121     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
122     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
123     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
124     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
125     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
126     0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
127     0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
128     0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
129     0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
130     0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
131     0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
132     0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
133     0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
134     0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
135     0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
136     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
137     0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
138     0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
139     0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
140     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
141     0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
142     0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
143     0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
144     0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
145     0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
146   },
147   /* User mapping -- default to codes for direct font mapping */
148   [USER_MAP] = {
149     0xf000, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007,
150     0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f,
151     0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
152     0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
153     0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
154     0xf028, 0xf029, 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f,
155     0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
156     0xf038, 0xf039, 0xf03a, 0xf03b, 0xf03c, 0xf03d, 0xf03e, 0xf03f,
157     0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
158     0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f,
159     0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, 0xf056, 0xf057,
160     0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
161     0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067,
162     0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, 0xf06d, 0xf06e, 0xf06f,
163     0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
164     0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f,
165     0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
166     0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
167     0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
168     0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
169     0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6, 0xf0a7,
170     0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae, 0xf0af,
171     0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xf0b6, 0xf0b7,
172     0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be, 0xf0bf,
173     0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6, 0xf0c7,
174     0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb, 0xf0cc, 0xf0cd, 0xf0ce, 0xf0cf,
175     0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d7,
176     0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc, 0xf0dd, 0xf0de, 0xf0df,
177     0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
178     0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
179     0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
180     0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
181   }
182 };
183 
184 /* The standard kernel character-to-font mappings are not invertible
185    -- this is just a best effort. */
186 
187 #define MAX_GLYPH 512		/* Max possible glyph value */
188 
189 static enum translation_map inv_translate[MAX_NR_CONSOLES];
190 
191 #define UNI_DIRS	32U
192 #define UNI_DIR_ROWS	32U
193 #define UNI_ROW_GLYPHS	64U
194 
195 #define UNI_DIR_BITS		GENMASK(15, 11)
196 #define UNI_ROW_BITS		GENMASK(10,  6)
197 #define UNI_GLYPH_BITS		GENMASK( 5,  0)
198 
199 #define UNI_DIR(uni)		FIELD_GET(UNI_DIR_BITS, (uni))
200 #define UNI_ROW(uni)		FIELD_GET(UNI_ROW_BITS, (uni))
201 #define UNI_GLYPH(uni)		FIELD_GET(UNI_GLYPH_BITS, (uni))
202 
203 #define UNI(dir, row, glyph)	(FIELD_PREP(UNI_DIR_BITS, (dir)) | \
204 				 FIELD_PREP(UNI_ROW_BITS, (row)) | \
205 				 FIELD_PREP(UNI_GLYPH_BITS, (glyph)))
206 
207 /**
208  * struct uni_pagedict -- unicode directory
209  *
210  * @uni_pgdir: 32*32*64 table with glyphs
211  * @refcount: reference count of this structure
212  * @sum: checksum
213  * @inverse_translations: best-effort inverse mapping
214  * @inverse_trans_unicode: best-effort inverse mapping to unicode
215  */
216 struct uni_pagedict {
217 	u16		**uni_pgdir[UNI_DIRS];
218 	unsigned long	refcount;
219 	unsigned long	sum;
220 	unsigned char	*inverse_translations[LAST_MAP + 1];
221 	u16		*inverse_trans_unicode;
222 };
223 
224 static struct uni_pagedict *dflt;
225 
set_inverse_transl(struct vc_data * conp,struct uni_pagedict * dict,enum translation_map m)226 static void set_inverse_transl(struct vc_data *conp, struct uni_pagedict *dict,
227 	       enum translation_map m)
228 {
229 	unsigned short *t = translations[m];
230 	unsigned char *inv;
231 
232 	if (!dict)
233 		return;
234 	inv = dict->inverse_translations[m];
235 
236 	if (!inv) {
237 		inv = dict->inverse_translations[m] = kmalloc(MAX_GLYPH,
238 				GFP_KERNEL);
239 		if (!inv)
240 			return;
241 	}
242 	memset(inv, 0, MAX_GLYPH);
243 
244 	for (unsigned int ch = 0; ch < ARRAY_SIZE(translations[m]); ch++) {
245 		int glyph = conv_uni_to_pc(conp, t[ch]);
246 		if (glyph >= 0 && glyph < MAX_GLYPH && inv[glyph] < 32) {
247 			/* prefer '-' above SHY etc. */
248 			inv[glyph] = ch;
249 		}
250 	}
251 }
252 
set_inverse_trans_unicode(struct uni_pagedict * dict)253 static void set_inverse_trans_unicode(struct uni_pagedict *dict)
254 {
255 	unsigned int d, r, g;
256 	u16 *inv;
257 
258 	if (!dict)
259 		return;
260 
261 	inv = dict->inverse_trans_unicode;
262 	if (!inv) {
263 		inv = dict->inverse_trans_unicode = kmalloc_array(MAX_GLYPH,
264 				sizeof(*inv), GFP_KERNEL);
265 		if (!inv)
266 			return;
267 	}
268 	memset(inv, 0, MAX_GLYPH * sizeof(*inv));
269 
270 	for (d = 0; d < UNI_DIRS; d++) {
271 		u16 **dir = dict->uni_pgdir[d];
272 		if (!dir)
273 			continue;
274 		for (r = 0; r < UNI_DIR_ROWS; r++) {
275 			u16 *row = dir[r];
276 			if (!row)
277 				continue;
278 			for (g = 0; g < UNI_ROW_GLYPHS; g++) {
279 				u16 glyph = row[g];
280 				if (glyph < MAX_GLYPH && inv[glyph] < 32)
281 					inv[glyph] = UNI(d, r, g);
282 			}
283 		}
284 	}
285 }
286 
set_translate(enum translation_map m,struct vc_data * vc)287 unsigned short *set_translate(enum translation_map m, struct vc_data *vc)
288 {
289 	inv_translate[vc->vc_num] = m;
290 	return translations[m];
291 }
292 
293 /*
294  * Inverse translation is impossible for several reasons:
295  * 1. The font<->character maps are not 1-1.
296  * 2. The text may have been written while a different translation map
297  *    was active.
298  * Still, it is now possible to a certain extent to cut and paste non-ASCII.
299  */
inverse_translate(const struct vc_data * conp,u16 glyph,bool use_unicode)300 u16 inverse_translate(const struct vc_data *conp, u16 glyph, bool use_unicode)
301 {
302 	struct uni_pagedict *p;
303 	enum translation_map m;
304 
305 	if (glyph >= MAX_GLYPH)
306 		return 0;
307 
308 	p = *conp->uni_pagedict_loc;
309 	if (!p)
310 		return glyph;
311 
312 	if (use_unicode) {
313 		if (!p->inverse_trans_unicode)
314 			return glyph;
315 
316 		return p->inverse_trans_unicode[glyph];
317 	}
318 
319 	m = inv_translate[conp->vc_num];
320 	if (!p->inverse_translations[m])
321 		return glyph;
322 
323 	return p->inverse_translations[m][glyph];
324 }
325 EXPORT_SYMBOL_GPL(inverse_translate);
326 
update_user_maps(void)327 static void update_user_maps(void)
328 {
329 	int i;
330 	struct uni_pagedict *p, *q = NULL;
331 
332 	for (i = 0; i < MAX_NR_CONSOLES; i++) {
333 		if (!vc_cons_allocated(i))
334 			continue;
335 		p = *vc_cons[i].d->uni_pagedict_loc;
336 		if (p && p != q) {
337 			set_inverse_transl(vc_cons[i].d, p, USER_MAP);
338 			set_inverse_trans_unicode(p);
339 			q = p;
340 		}
341 	}
342 }
343 
344 /*
345  * Load customizable translation table
346  * arg points to a 256 byte translation table.
347  *
348  * The "old" variants are for translation directly to font (using the
349  * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
350  * Unicodes explicitly.
351  */
con_set_trans_old(unsigned char __user * arg)352 int con_set_trans_old(unsigned char __user * arg)
353 {
354 	unsigned short inbuf[E_TABSZ];
355 	unsigned int i;
356 	unsigned char ch;
357 
358 	for (i = 0; i < ARRAY_SIZE(inbuf); i++) {
359 		if (get_user(ch, &arg[i]))
360 			return -EFAULT;
361 		inbuf[i] = UNI_DIRECT_BASE | ch;
362 	}
363 
364 	console_lock();
365 	memcpy(translations[USER_MAP], inbuf, sizeof(inbuf));
366 	update_user_maps();
367 	console_unlock();
368 	return 0;
369 }
370 
con_get_trans_old(unsigned char __user * arg)371 int con_get_trans_old(unsigned char __user * arg)
372 {
373 	int i, ch;
374 	unsigned short *p = translations[USER_MAP];
375 	unsigned char outbuf[E_TABSZ];
376 
377 	console_lock();
378 	for (i = 0; i < ARRAY_SIZE(outbuf); i++)
379 	{
380 		ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
381 		outbuf[i] = (ch & ~0xff) ? 0 : ch;
382 	}
383 	console_unlock();
384 
385 	return copy_to_user(arg, outbuf, sizeof(outbuf)) ? -EFAULT : 0;
386 }
387 
con_set_trans_new(ushort __user * arg)388 int con_set_trans_new(ushort __user * arg)
389 {
390 	unsigned short inbuf[E_TABSZ];
391 
392 	if (copy_from_user(inbuf, arg, sizeof(inbuf)))
393 		return -EFAULT;
394 
395 	console_lock();
396 	memcpy(translations[USER_MAP], inbuf, sizeof(inbuf));
397 	update_user_maps();
398 	console_unlock();
399 	return 0;
400 }
401 
con_get_trans_new(ushort __user * arg)402 int con_get_trans_new(ushort __user * arg)
403 {
404 	unsigned short outbuf[E_TABSZ];
405 
406 	console_lock();
407 	memcpy(outbuf, translations[USER_MAP], sizeof(outbuf));
408 	console_unlock();
409 
410 	return copy_to_user(arg, outbuf, sizeof(outbuf)) ? -EFAULT : 0;
411 }
412 
413 /*
414  * Unicode -> current font conversion
415  *
416  * A font has at most 512 chars, usually 256.
417  * But one font position may represent several Unicode chars.
418  * A hashtable is somewhat of a pain to deal with, so use a
419  * "paged table" instead.  Simulation has shown the memory cost of
420  * this 3-level paged table scheme to be comparable to a hash table.
421  */
422 
423 extern u8 dfont_unicount[];	/* Defined in console_defmap.c */
424 extern u16 dfont_unitable[];
425 
con_release_unimap(struct uni_pagedict * dict)426 static void con_release_unimap(struct uni_pagedict *dict)
427 {
428 	unsigned int d, r;
429 
430 	if (dict == dflt)
431 		dflt = NULL;
432 
433 	for (d = 0; d < UNI_DIRS; d++) {
434 		u16 **dir = dict->uni_pgdir[d];
435 		if (dir != NULL) {
436 			for (r = 0; r < UNI_DIR_ROWS; r++)
437 				kfree(dir[r]);
438 			kfree(dir);
439 		}
440 		dict->uni_pgdir[d] = NULL;
441 	}
442 
443 	for (r = 0; r < ARRAY_SIZE(dict->inverse_translations); r++) {
444 		kfree(dict->inverse_translations[r]);
445 		dict->inverse_translations[r] = NULL;
446 	}
447 
448 	kfree(dict->inverse_trans_unicode);
449 	dict->inverse_trans_unicode = NULL;
450 }
451 
452 /* Caller must hold the console lock */
con_free_unimap(struct vc_data * vc)453 void con_free_unimap(struct vc_data *vc)
454 {
455 	struct uni_pagedict *p;
456 
457 	p = *vc->uni_pagedict_loc;
458 	if (!p)
459 		return;
460 	*vc->uni_pagedict_loc = NULL;
461 	if (--p->refcount)
462 		return;
463 	con_release_unimap(p);
464 	kfree(p);
465 }
466 
con_unify_unimap(struct vc_data * conp,struct uni_pagedict * dict1)467 static int con_unify_unimap(struct vc_data *conp, struct uni_pagedict *dict1)
468 {
469 	struct uni_pagedict *dict2;
470 	unsigned int cons, d, r;
471 
472 	for (cons = 0; cons < MAX_NR_CONSOLES; cons++) {
473 		if (!vc_cons_allocated(cons))
474 			continue;
475 		dict2 = *vc_cons[cons].d->uni_pagedict_loc;
476 		if (!dict2 || dict2 == dict1 || dict2->sum != dict1->sum)
477 			continue;
478 		for (d = 0; d < UNI_DIRS; d++) {
479 			u16 **dir1 = dict1->uni_pgdir[d];
480 			u16 **dir2 = dict2->uni_pgdir[d];
481 			if (!dir1 && !dir2)
482 				continue;
483 			if (!dir1 || !dir2)
484 				break;
485 			for (r = 0; r < UNI_DIR_ROWS; r++) {
486 				if (!dir1[r] && !dir2[r])
487 					continue;
488 				if (!dir1[r] || !dir2[r])
489 					break;
490 				if (memcmp(dir1[r], dir2[r], UNI_ROW_GLYPHS *
491 							sizeof(*dir1[r])))
492 					break;
493 			}
494 			if (r < UNI_DIR_ROWS)
495 				break;
496 		}
497 		if (d == UNI_DIRS) {
498 			dict2->refcount++;
499 			*conp->uni_pagedict_loc = dict2;
500 			con_release_unimap(dict1);
501 			kfree(dict1);
502 			return 1;
503 		}
504 	}
505 	return 0;
506 }
507 
508 static int
con_insert_unipair(struct uni_pagedict * p,u_short unicode,u_short fontpos)509 con_insert_unipair(struct uni_pagedict *p, u_short unicode, u_short fontpos)
510 {
511 	u16 **dir, *row;
512 	unsigned int n;
513 
514 	n = UNI_DIR(unicode);
515 	dir = p->uni_pgdir[n];
516 	if (!dir) {
517 		dir = p->uni_pgdir[n] = kcalloc(UNI_DIR_ROWS, sizeof(*dir),
518 				GFP_KERNEL);
519 		if (!dir)
520 			return -ENOMEM;
521 	}
522 
523 	n = UNI_ROW(unicode);
524 	row = dir[n];
525 	if (!row) {
526 		row = dir[n] = kmalloc_array(UNI_ROW_GLYPHS, sizeof(*row),
527 				GFP_KERNEL);
528 		if (!row)
529 			return -ENOMEM;
530 		/* No glyphs for the characters (yet) */
531 		memset(row, 0xff, UNI_ROW_GLYPHS * sizeof(*row));
532 	}
533 
534 	row[UNI_GLYPH(unicode)] = fontpos;
535 
536 	p->sum += (fontpos << 20U) + unicode;
537 
538 	return 0;
539 }
540 
con_allocate_new(struct vc_data * vc)541 static int con_allocate_new(struct vc_data *vc)
542 {
543 	struct uni_pagedict *new, *old = *vc->uni_pagedict_loc;
544 
545 	new = kzalloc(sizeof(*new), GFP_KERNEL);
546 	if (!new)
547 		return -ENOMEM;
548 
549 	new->refcount = 1;
550 	*vc->uni_pagedict_loc = new;
551 
552 	if (old)
553 		old->refcount--;
554 
555 	return 0;
556 }
557 
558 /* Caller must hold the lock */
con_do_clear_unimap(struct vc_data * vc)559 static int con_do_clear_unimap(struct vc_data *vc)
560 {
561 	struct uni_pagedict *old = *vc->uni_pagedict_loc;
562 
563 	if (!old || old->refcount > 1)
564 		return con_allocate_new(vc);
565 
566 	old->sum = 0;
567 	con_release_unimap(old);
568 
569 	return 0;
570 }
571 
con_clear_unimap(struct vc_data * vc)572 int con_clear_unimap(struct vc_data *vc)
573 {
574 	int ret;
575 	console_lock();
576 	ret = con_do_clear_unimap(vc);
577 	console_unlock();
578 	return ret;
579 }
580 
con_unshare_unimap(struct vc_data * vc,struct uni_pagedict * old)581 static struct uni_pagedict *con_unshare_unimap(struct vc_data *vc,
582 		struct uni_pagedict *old)
583 {
584 	struct uni_pagedict *new;
585 	unsigned int d, r, g;
586 	int ret;
587 	u16 uni = 0;
588 
589 	ret = con_allocate_new(vc);
590 	if (ret)
591 		return ERR_PTR(ret);
592 
593 	new = *vc->uni_pagedict_loc;
594 
595 	/*
596 	 * uni_pgdir is a 32*32*64 table with rows allocated when its first
597 	 * entry is added. The unicode value must still be incremented for
598 	 * empty rows. We are copying entries from "old" to "new".
599 	 */
600 	for (d = 0; d < UNI_DIRS; d++) {
601 		u16 **dir = old->uni_pgdir[d];
602 		if (!dir) {
603 			/* Account for empty table */
604 			uni += UNI_DIR_ROWS * UNI_ROW_GLYPHS;
605 			continue;
606 		}
607 
608 		for (r = 0; r < UNI_DIR_ROWS; r++) {
609 			u16 *row = dir[r];
610 			if (!row) {
611 				/* Account for row of 64 empty entries */
612 				uni += UNI_ROW_GLYPHS;
613 				continue;
614 			}
615 
616 			for (g = 0; g < UNI_ROW_GLYPHS; g++, uni++) {
617 				if (row[g] == 0xffff)
618 					continue;
619 				/*
620 				 * Found one, copy entry for unicode uni with
621 				 * fontpos value row[g].
622 				 */
623 				ret = con_insert_unipair(new, uni, row[g]);
624 				if (ret) {
625 					old->refcount++;
626 					*vc->uni_pagedict_loc = old;
627 					con_release_unimap(new);
628 					kfree(new);
629 					return ERR_PTR(ret);
630 				}
631 			}
632 		}
633 	}
634 
635 	return new;
636 }
637 
con_set_unimap(struct vc_data * vc,ushort ct,struct unipair __user * list)638 int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
639 {
640 	int err = 0, err1;
641 	struct uni_pagedict *dict;
642 	struct unipair *unilist, *plist;
643 
644 	if (!ct)
645 		return 0;
646 
647 	unilist = vmemdup_user(list, array_size(sizeof(*unilist), ct));
648 	if (IS_ERR(unilist))
649 		return PTR_ERR(unilist);
650 
651 	console_lock();
652 
653 	/* Save original vc_unipagdir_loc in case we allocate a new one */
654 	dict = *vc->uni_pagedict_loc;
655 	if (!dict) {
656 		err = -EINVAL;
657 		goto out_unlock;
658 	}
659 
660 	if (dict->refcount > 1) {
661 		dict = con_unshare_unimap(vc, dict);
662 		if (IS_ERR(dict)) {
663 			err = PTR_ERR(dict);
664 			goto out_unlock;
665 		}
666 	} else if (dict == dflt) {
667 		dflt = NULL;
668 	}
669 
670 	/*
671 	 * Insert user specified unicode pairs into new table.
672 	 */
673 	for (plist = unilist; ct; ct--, plist++) {
674 		err1 = con_insert_unipair(dict, plist->unicode, plist->fontpos);
675 		if (err1)
676 			err = err1;
677 	}
678 
679 	/*
680 	 * Merge with fontmaps of any other virtual consoles.
681 	 */
682 	if (con_unify_unimap(vc, dict))
683 		goto out_unlock;
684 
685 	for (enum translation_map m = FIRST_MAP; m <= LAST_MAP; m++)
686 		set_inverse_transl(vc, dict, m);
687 	set_inverse_trans_unicode(dict);
688 
689 out_unlock:
690 	console_unlock();
691 	kvfree(unilist);
692 	return err;
693 }
694 
695 /**
696  *	con_set_default_unimap	-	set default unicode map
697  *	@vc: the console we are updating
698  *
699  *	Loads the unimap for the hardware font, as defined in uni_hash.tbl.
700  *	The representation used was the most compact I could come up
701  *	with.  This routine is executed at video setup, and when the
702  *	PIO_FONTRESET ioctl is called.
703  *
704  *	The caller must hold the console lock
705  */
con_set_default_unimap(struct vc_data * vc)706 int con_set_default_unimap(struct vc_data *vc)
707 {
708 	struct uni_pagedict *dict;
709 	unsigned int fontpos, count;
710 	int err = 0, err1;
711 	u16 *dfont;
712 
713 	if (dflt) {
714 		dict = *vc->uni_pagedict_loc;
715 		if (dict == dflt)
716 			return 0;
717 
718 		dflt->refcount++;
719 		*vc->uni_pagedict_loc = dflt;
720 		if (dict && !--dict->refcount) {
721 			con_release_unimap(dict);
722 			kfree(dict);
723 		}
724 		return 0;
725 	}
726 
727 	/* The default font is always 256 characters */
728 
729 	err = con_do_clear_unimap(vc);
730 	if (err)
731 		return err;
732 
733 	dict = *vc->uni_pagedict_loc;
734 	dfont = dfont_unitable;
735 
736 	for (fontpos = 0; fontpos < 256U; fontpos++)
737 		for (count = dfont_unicount[fontpos]; count; count--) {
738 			err1 = con_insert_unipair(dict, *(dfont++), fontpos);
739 			if (err1)
740 				err = err1;
741 		}
742 
743 	if (con_unify_unimap(vc, dict)) {
744 		dflt = *vc->uni_pagedict_loc;
745 		return err;
746 	}
747 
748 	for (enum translation_map m = FIRST_MAP; m <= LAST_MAP; m++)
749 		set_inverse_transl(vc, dict, m);
750 	set_inverse_trans_unicode(dict);
751 	dflt = dict;
752 	return err;
753 }
754 EXPORT_SYMBOL(con_set_default_unimap);
755 
756 /**
757  *	con_copy_unimap		-	copy unimap between two vts
758  *	@dst_vc: target
759  *	@src_vc: source
760  *
761  *	The caller must hold the console lock when invoking this method
762  */
con_copy_unimap(struct vc_data * dst_vc,struct vc_data * src_vc)763 int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
764 {
765 	struct uni_pagedict *src;
766 
767 	if (!*src_vc->uni_pagedict_loc)
768 		return -EINVAL;
769 	if (*dst_vc->uni_pagedict_loc == *src_vc->uni_pagedict_loc)
770 		return 0;
771 	con_free_unimap(dst_vc);
772 	src = *src_vc->uni_pagedict_loc;
773 	src->refcount++;
774 	*dst_vc->uni_pagedict_loc = src;
775 	return 0;
776 }
777 EXPORT_SYMBOL(con_copy_unimap);
778 
779 /*
780  *	con_get_unimap		-	get the unicode map
781  *
782  *	Read the console unicode data for this console. Called from the ioctl
783  *	handlers.
784  */
con_get_unimap(struct vc_data * vc,ushort ct,ushort __user * uct,struct unipair __user * list)785 int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct,
786 		struct unipair __user *list)
787 {
788 	ushort ect;
789 	struct uni_pagedict *dict;
790 	struct unipair *unilist;
791 	unsigned int d, r, g;
792 	int ret = 0;
793 
794 	unilist = kvmalloc_array(ct, sizeof(*unilist), GFP_KERNEL);
795 	if (!unilist)
796 		return -ENOMEM;
797 
798 	console_lock();
799 
800 	ect = 0;
801 	dict = *vc->uni_pagedict_loc;
802 	if (!dict)
803 		goto unlock;
804 
805 	for (d = 0; d < UNI_DIRS; d++) {
806 		u16 **dir = dict->uni_pgdir[d];
807 		if (!dir)
808 			continue;
809 
810 		for (r = 0; r < UNI_DIR_ROWS; r++) {
811 			u16 *row = dir[r];
812 			if (!row)
813 				continue;
814 
815 			for (g = 0; g < UNI_ROW_GLYPHS; g++, row++) {
816 				if (*row >= MAX_GLYPH)
817 					continue;
818 				if (ect < ct) {
819 					unilist[ect].unicode = UNI(d, r, g);
820 					unilist[ect].fontpos = *row;
821 				}
822 				ect++;
823 			}
824 		}
825 	}
826 unlock:
827 	console_unlock();
828 	if (copy_to_user(list, unilist, min(ect, ct) * sizeof(*unilist)))
829 		ret = -EFAULT;
830 	if (put_user(ect, uct))
831 		ret = -EFAULT;
832 	kvfree(unilist);
833 	return ret ? ret : (ect <= ct) ? 0 : -ENOMEM;
834 }
835 
836 /*
837  * Always use USER_MAP. These functions are used by the keyboard,
838  * which shouldn't be affected by G0/G1 switching, etc.
839  * If the user map still contains default values, i.e. the
840  * direct-to-font mapping, then assume user is using Latin1.
841  *
842  * FIXME: at some point we need to decide if we want to lock the table
843  * update element itself via the keyboard_event_lock for consistency with the
844  * keyboard driver as well as the consoles
845  */
846 /* may be called during an interrupt */
conv_8bit_to_uni(unsigned char c)847 u32 conv_8bit_to_uni(unsigned char c)
848 {
849 	unsigned short uni = translations[USER_MAP][c];
850 	return uni == (0xf000 | c) ? c : uni;
851 }
852 
conv_uni_to_8bit(u32 uni)853 int conv_uni_to_8bit(u32 uni)
854 {
855 	int c;
856 	for (c = 0; c < ARRAY_SIZE(translations[USER_MAP]); c++)
857 		if (translations[USER_MAP][c] == uni ||
858 		   (translations[USER_MAP][c] == (c | 0xf000) && uni == c))
859 			return c;
860 	return -1;
861 }
862 
conv_uni_to_pc(struct vc_data * conp,long ucs)863 int conv_uni_to_pc(struct vc_data *conp, long ucs)
864 {
865 	struct uni_pagedict *dict;
866 	u16 **dir, *row, glyph;
867 
868 	/* Only 16-bit codes supported at this time */
869 	if (ucs > 0xffff)
870 		return -4;		/* Not found */
871 	else if (ucs < 0x20)
872 		return -1;		/* Not a printable character */
873 	else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
874 		return -2;			/* Zero-width space */
875 	/*
876 	 * UNI_DIRECT_BASE indicates the start of the region in the User Zone
877 	 * which always has a 1:1 mapping to the currently loaded font.  The
878 	 * UNI_DIRECT_MASK indicates the bit span of the region.
879 	 */
880 	else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
881 		return ucs & UNI_DIRECT_MASK;
882 
883 	dict = *conp->uni_pagedict_loc;
884 	if (!dict)
885 		return -3;
886 
887 	dir = dict->uni_pgdir[UNI_DIR(ucs)];
888 	if (!dir)
889 		return -4;
890 
891 	row = dir[UNI_ROW(ucs)];
892 	if (!row)
893 		return -4;
894 
895 	glyph = row[UNI_GLYPH(ucs)];
896 	if (glyph >= MAX_GLYPH)
897 		return -4;
898 
899 	return glyph;
900 }
901 
902 /*
903  * This is called at sys_setup time, after memory and the console are
904  * initialized.  It must be possible to call kmalloc(..., GFP_KERNEL)
905  * from this function, hence the call from sys_setup.
906  */
907 void __init
console_map_init(void)908 console_map_init(void)
909 {
910 	int i;
911 
912 	for (i = 0; i < MAX_NR_CONSOLES; i++)
913 		if (vc_cons_allocated(i) && !*vc_cons[i].d->uni_pagedict_loc)
914 			con_set_default_unimap(vc_cons[i].d);
915 }
916 
917