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