Linux-libre 4.10.7-gnu
[librecmc/linux-libre.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
326         if (!access_ok(VERIFY_READ, arg, E_TABSZ))
327                 return -EFAULT;
328
329         for (i = 0; i < E_TABSZ ; i++) {
330                 unsigned char uc;
331                 __get_user(uc, arg+i);
332                 inbuf[i] = UNI_DIRECT_BASE | uc;
333         }
334
335         console_lock();
336         memcpy(translations[USER_MAP], inbuf, sizeof(inbuf));
337         update_user_maps();
338         console_unlock();
339         return 0;
340 }
341
342 int con_get_trans_old(unsigned char __user * arg)
343 {
344         int i, ch;
345         unsigned short *p = translations[USER_MAP];
346         unsigned char outbuf[E_TABSZ];
347
348         if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
349                 return -EFAULT;
350
351         console_lock();
352         for (i = 0; i < E_TABSZ ; i++)
353         {
354                 ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
355                 outbuf[i] = (ch & ~0xff) ? 0 : ch;
356         }
357         console_unlock();
358
359         for (i = 0; i < E_TABSZ ; i++)
360                 __put_user(outbuf[i], arg+i);
361         return 0;
362 }
363
364 int con_set_trans_new(ushort __user * arg)
365 {
366         int i;
367         unsigned short inbuf[E_TABSZ];
368
369         if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
370                 return -EFAULT;
371
372         for (i = 0; i < E_TABSZ ; i++)
373                 __get_user(inbuf[i], arg+i);
374
375         console_lock();
376         memcpy(translations[USER_MAP], inbuf, sizeof(inbuf));
377         update_user_maps();
378         console_unlock();
379         return 0;
380 }
381
382 int con_get_trans_new(ushort __user * arg)
383 {
384         int i;
385         unsigned short outbuf[E_TABSZ];
386
387         if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
388                 return -EFAULT;
389
390         console_lock();
391         memcpy(outbuf, translations[USER_MAP], sizeof(outbuf));
392         console_unlock();
393
394         for (i = 0; i < E_TABSZ ; i++)
395                 __put_user(outbuf[i], arg+i);
396         return 0;
397 }
398
399 /*
400  * Unicode -> current font conversion 
401  *
402  * A font has at most 512 chars, usually 256.
403  * But one font position may represent several Unicode chars.
404  * A hashtable is somewhat of a pain to deal with, so use a
405  * "paged table" instead.  Simulation has shown the memory cost of
406  * this 3-level paged table scheme to be comparable to a hash table.
407  */
408
409 extern u8 dfont_unicount[];     /* Defined in console_defmap.c */
410 extern u16 dfont_unitable[];
411
412 static void con_release_unimap(struct uni_pagedir *p)
413 {
414         u16 **p1;
415         int i, j;
416
417         if (p == dflt) dflt = NULL;  
418         for (i = 0; i < 32; i++) {
419                 p1 = p->uni_pgdir[i];
420                 if (p1 != NULL) {
421                         for (j = 0; j < 32; j++)
422                                 kfree(p1[j]);
423                         kfree(p1);
424                 }
425                 p->uni_pgdir[i] = NULL;
426         }
427         for (i = 0; i < 4; i++) {
428                 kfree(p->inverse_translations[i]);
429                 p->inverse_translations[i] = NULL;
430         }
431         kfree(p->inverse_trans_unicode);
432         p->inverse_trans_unicode = NULL;
433 }
434
435 /* Caller must hold the console lock */
436 void con_free_unimap(struct vc_data *vc)
437 {
438         struct uni_pagedir *p;
439
440         p = *vc->vc_uni_pagedir_loc;
441         if (!p)
442                 return;
443         *vc->vc_uni_pagedir_loc = NULL;
444         if (--p->refcount)
445                 return;
446         con_release_unimap(p);
447         kfree(p);
448 }
449   
450 static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
451 {
452         int i, j, k;
453         struct uni_pagedir *q;
454         
455         for (i = 0; i < MAX_NR_CONSOLES; i++) {
456                 if (!vc_cons_allocated(i))
457                         continue;
458                 q = *vc_cons[i].d->vc_uni_pagedir_loc;
459                 if (!q || q == p || q->sum != p->sum)
460                         continue;
461                 for (j = 0; j < 32; j++) {
462                         u16 **p1, **q1;
463                         p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
464                         if (!p1 && !q1)
465                                 continue;
466                         if (!p1 || !q1)
467                                 break;
468                         for (k = 0; k < 32; k++) {
469                                 if (!p1[k] && !q1[k])
470                                         continue;
471                                 if (!p1[k] || !q1[k])
472                                         break;
473                                 if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
474                                         break;
475                         }
476                         if (k < 32)
477                                 break;
478                 }
479                 if (j == 32) {
480                         q->refcount++;
481                         *conp->vc_uni_pagedir_loc = q;
482                         con_release_unimap(p);
483                         kfree(p);
484                         return 1;
485                 }
486         }
487         return 0;
488 }
489
490 static int
491 con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
492 {
493         int i, n;
494         u16 **p1, *p2;
495
496         p1 = p->uni_pgdir[n = unicode >> 11];
497         if (!p1) {
498                 p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
499                 if (!p1) return -ENOMEM;
500                 for (i = 0; i < 32; i++)
501                         p1[i] = NULL;
502         }
503
504         p2 = p1[n = (unicode >> 6) & 0x1f];
505         if (!p2) {
506                 p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
507                 if (!p2) return -ENOMEM;
508                 memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
509         }
510
511         p2[unicode & 0x3f] = fontpos;
512         
513         p->sum += (fontpos << 20) + unicode;
514
515         return 0;
516 }
517
518 /* Caller must hold the lock */
519 static int con_do_clear_unimap(struct vc_data *vc)
520 {
521         struct uni_pagedir *p, *q;
522
523         p = *vc->vc_uni_pagedir_loc;
524         if (!p || --p->refcount) {
525                 q = kzalloc(sizeof(*p), GFP_KERNEL);
526                 if (!q) {
527                         if (p)
528                                 p->refcount++;
529                         return -ENOMEM;
530                 }
531                 q->refcount=1;
532                 *vc->vc_uni_pagedir_loc = q;
533         } else {
534                 if (p == dflt) dflt = NULL;
535                 p->refcount++;
536                 p->sum = 0;
537                 con_release_unimap(p);
538         }
539         return 0;
540 }
541
542 int con_clear_unimap(struct vc_data *vc)
543 {
544         int ret;
545         console_lock();
546         ret = con_do_clear_unimap(vc);
547         console_unlock();
548         return ret;
549 }
550         
551 int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
552 {
553         int err = 0, err1, i;
554         struct uni_pagedir *p, *q;
555         struct unipair *unilist, *plist;
556
557         if (!ct)
558                 return 0;
559
560         unilist = kmalloc_array(ct, sizeof(struct unipair), GFP_KERNEL);
561         if (!unilist)
562                 return -ENOMEM;
563
564         for (i = ct, plist = unilist; i; i--, plist++, list++) {
565                 __get_user(plist->unicode, &list->unicode);
566                 __get_user(plist->fontpos, &list->fontpos);
567         }
568
569         console_lock();
570
571         /* Save original vc_unipagdir_loc in case we allocate a new one */
572         p = *vc->vc_uni_pagedir_loc;
573
574         if (!p) {
575                 err = -EINVAL;
576
577                 goto out_unlock;
578         }
579         
580         if (p->refcount > 1) {
581                 int j, k;
582                 u16 **p1, *p2, l;
583                 
584                 err1 = con_do_clear_unimap(vc);
585                 if (err1) {
586                         err = err1;
587                         goto out_unlock;
588                 }
589                 
590                 /*
591                  * Since refcount was > 1, con_clear_unimap() allocated a
592                  * a new uni_pagedir for this vc.  Re: p != q
593                  */
594                 q = *vc->vc_uni_pagedir_loc;
595
596                 /*
597                  * uni_pgdir is a 32*32*64 table with rows allocated
598                  * when its first entry is added.  The unicode value must
599                  * still be incremented for empty rows.  We are copying
600                  * entries from "p" (old) to "q" (new).
601                  */
602                 l = 0;          /* unicode value */
603                 for (i = 0; i < 32; i++) {
604                 p1 = p->uni_pgdir[i];
605                 if (p1)
606                         for (j = 0; j < 32; j++) {
607                         p2 = p1[j];
608                         if (p2) {
609                                 for (k = 0; k < 64; k++, l++)
610                                 if (p2[k] != 0xffff) {
611                                         /*
612                                          * Found one, copy entry for unicode
613                                          * l with fontpos value p2[k].
614                                          */
615                                         err1 = con_insert_unipair(q, l, p2[k]);
616                                         if (err1) {
617                                                 p->refcount++;
618                                                 *vc->vc_uni_pagedir_loc = p;
619                                                 con_release_unimap(q);
620                                                 kfree(q);
621                                                 err = err1;
622                                                 goto out_unlock;
623                                         }
624                                 }
625                         } else {
626                                 /* Account for row of 64 empty entries */
627                                 l += 64;
628                         }
629                 }
630                 else
631                         /* Account for empty table */
632                         l += 32 * 64;
633                 }
634
635                 /*
636                  * Finished copying font table, set vc_uni_pagedir to new table
637                  */
638                 p = q;
639         } else if (p == dflt) {
640                 dflt = NULL;
641         }
642
643         /*
644          * Insert user specified unicode pairs into new table.
645          */
646         for (plist = unilist; ct; ct--, plist++) {
647                 err1 = con_insert_unipair(p, plist->unicode, plist->fontpos);
648                 if (err1)
649                         err = err1;
650         }
651         
652         /*
653          * Merge with fontmaps of any other virtual consoles.
654          */
655         if (con_unify_unimap(vc, p))
656                 goto out_unlock;
657
658         for (i = 0; i <= 3; i++)
659                 set_inverse_transl(vc, p, i); /* Update inverse translations */
660         set_inverse_trans_unicode(vc, p);
661
662 out_unlock:
663         console_unlock();
664         kfree(unilist);
665         return err;
666 }
667
668 /**
669  *      con_set_default_unimap  -       set default unicode map
670  *      @vc: the console we are updating
671  *
672  *      Loads the unimap for the hardware font, as defined in uni_hash.tbl.
673  *      The representation used was the most compact I could come up
674  *      with.  This routine is executed at video setup, and when the
675  *      PIO_FONTRESET ioctl is called. 
676  *
677  *      The caller must hold the console lock
678  */
679 int con_set_default_unimap(struct vc_data *vc)
680 {
681         int i, j, err = 0, err1;
682         u16 *q;
683         struct uni_pagedir *p;
684
685         if (dflt) {
686                 p = *vc->vc_uni_pagedir_loc;
687                 if (p == dflt)
688                         return 0;
689
690                 dflt->refcount++;
691                 *vc->vc_uni_pagedir_loc = dflt;
692                 if (p && !--p->refcount) {
693                         con_release_unimap(p);
694                         kfree(p);
695                 }
696                 return 0;
697         }
698         
699         /* The default font is always 256 characters */
700
701         err = con_do_clear_unimap(vc);
702         if (err)
703                 return err;
704     
705         p = *vc->vc_uni_pagedir_loc;
706         q = dfont_unitable;
707         
708         for (i = 0; i < 256; i++)
709                 for (j = dfont_unicount[i]; j; j--) {
710                         err1 = con_insert_unipair(p, *(q++), i);
711                         if (err1)
712                                 err = err1;
713                 }
714                         
715         if (con_unify_unimap(vc, p)) {
716                 dflt = *vc->vc_uni_pagedir_loc;
717                 return err;
718         }
719
720         for (i = 0; i <= 3; i++)
721                 set_inverse_transl(vc, p, i);   /* Update all inverse translations */
722         set_inverse_trans_unicode(vc, p);
723         dflt = p;
724         return err;
725 }
726 EXPORT_SYMBOL(con_set_default_unimap);
727
728 /**
729  *      con_copy_unimap         -       copy unimap between two vts
730  *      @dst_vc: target
731  *      @src_vt: source
732  *
733  *      The caller must hold the console lock when invoking this method
734  */
735 int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
736 {
737         struct uni_pagedir *q;
738
739         if (!*src_vc->vc_uni_pagedir_loc)
740                 return -EINVAL;
741         if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
742                 return 0;
743         con_free_unimap(dst_vc);
744         q = *src_vc->vc_uni_pagedir_loc;
745         q->refcount++;
746         *dst_vc->vc_uni_pagedir_loc = q;
747         return 0;
748 }
749 EXPORT_SYMBOL(con_copy_unimap);
750
751 /**
752  *      con_get_unimap          -       get the unicode map
753  *      @vc: the console to read from
754  *
755  *      Read the console unicode data for this console. Called from the ioctl
756  *      handlers.
757  */
758 int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
759 {
760         int i, j, k;
761         ushort ect;
762         u16 **p1, *p2;
763         struct uni_pagedir *p;
764         struct unipair *unilist, *plist;
765
766         unilist = kmalloc_array(ct, sizeof(struct unipair), GFP_KERNEL);
767         if (!unilist)
768                 return -ENOMEM;
769
770         console_lock();
771
772         ect = 0;
773         if (*vc->vc_uni_pagedir_loc) {
774                 p = *vc->vc_uni_pagedir_loc;
775                 for (i = 0; i < 32; i++) {
776                 p1 = p->uni_pgdir[i];
777                 if (p1)
778                         for (j = 0; j < 32; j++) {
779                         p2 = *(p1++);
780                         if (p2)
781                                 for (k = 0; k < 64; k++, p2++) {
782                                         if (*p2 >= MAX_GLYPH)
783                                                 continue;
784                                         if (ect < ct) {
785                                                 unilist[ect].unicode =
786                                                         (i<<11)+(j<<6)+k;
787                                                 unilist[ect].fontpos = *p2;
788                                         }
789                                         ect++;
790                                 }
791                         }
792                 }
793         }
794         console_unlock();
795         for (i = min(ect, ct), plist = unilist; i; i--, list++, plist++) {
796                 __put_user(plist->unicode, &list->unicode);
797                 __put_user(plist->fontpos, &list->fontpos);
798         }
799         __put_user(ect, uct);
800         kfree(unilist);
801         return ((ect <= ct) ? 0 : -ENOMEM);
802 }
803
804 /*
805  * Always use USER_MAP. These functions are used by the keyboard,
806  * which shouldn't be affected by G0/G1 switching, etc.
807  * If the user map still contains default values, i.e. the
808  * direct-to-font mapping, then assume user is using Latin1.
809  *
810  * FIXME: at some point we need to decide if we want to lock the table
811  * update element itself via the keyboard_event_lock for consistency with the
812  * keyboard driver as well as the consoles
813  */
814 /* may be called during an interrupt */
815 u32 conv_8bit_to_uni(unsigned char c)
816 {
817         unsigned short uni = translations[USER_MAP][c];
818         return uni == (0xf000 | c) ? c : uni;
819 }
820
821 int conv_uni_to_8bit(u32 uni)
822 {
823         int c;
824         for (c = 0; c < 0x100; c++)
825                 if (translations[USER_MAP][c] == uni ||
826                    (translations[USER_MAP][c] == (c | 0xf000) && uni == c))
827                         return c;
828         return -1;
829 }
830
831 int
832 conv_uni_to_pc(struct vc_data *conp, long ucs) 
833 {
834         int h;
835         u16 **p1, *p2;
836         struct uni_pagedir *p;
837   
838         /* Only 16-bit codes supported at this time */
839         if (ucs > 0xffff)
840                 return -4;              /* Not found */
841         else if (ucs < 0x20)
842                 return -1;              /* Not a printable character */
843         else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
844                 return -2;                      /* Zero-width space */
845         /*
846          * UNI_DIRECT_BASE indicates the start of the region in the User Zone
847          * which always has a 1:1 mapping to the currently loaded font.  The
848          * UNI_DIRECT_MASK indicates the bit span of the region.
849          */
850         else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
851                 return ucs & UNI_DIRECT_MASK;
852   
853         if (!*conp->vc_uni_pagedir_loc)
854                 return -3;
855
856         p = *conp->vc_uni_pagedir_loc;
857         if ((p1 = p->uni_pgdir[ucs >> 11]) &&
858             (p2 = p1[(ucs >> 6) & 0x1f]) &&
859             (h = p2[ucs & 0x3f]) < MAX_GLYPH)
860                 return h;
861
862         return -4;              /* not found */
863 }
864
865 /*
866  * This is called at sys_setup time, after memory and the console are
867  * initialized.  It must be possible to call kmalloc(..., GFP_KERNEL)
868  * from this function, hence the call from sys_setup.
869  */
870 void __init 
871 console_map_init(void)
872 {
873         int i;
874         
875         for (i = 0; i < MAX_NR_CONSOLES; i++)
876                 if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
877                         con_set_default_unimap(vc_cons[i].d);
878 }
879