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