Merge branch 'for-6.9/amd-sfh' into for-linus
[sfrench/cifs-2.6.git] / drivers / tty / vt / consolemap.c
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
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
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
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  */
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
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  */
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
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
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
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
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 */
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
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
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
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 */
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
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
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
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_array_user(list, ct, sizeof(*unilist));
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  */
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  */
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  */
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 */
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
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
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
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