GNU Linux-libre 4.9.309-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
14 #include <linux/module.h>
15 #include <linux/kd.h>
16 #include <linux/errno.h>
17 #include <linux/mm.h>
18 #include <linux/slab.h>
19 #include <linux/init.h>
20 #include <linux/tty.h>
21 #include <asm/uaccess.h>
22 #include <linux/console.h>
23 #include <linux/consolemap.h>
24 #include <linux/vt_kern.h>
25
26 static unsigned short translations[][256] = {
27   /* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
28   {
29     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
30     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
31     0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
32     0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
33     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
34     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
35     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
36     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
37     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
38     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
39     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
40     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
41     0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
42     0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
43     0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
44     0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
45     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
46     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
47     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
48     0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
49     0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
50     0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
51     0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
52     0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
53     0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
54     0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
55     0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
56     0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
57     0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
58     0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
59     0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
60     0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
61   }, 
62   /* VT100 graphics mapped to Unicode */
63   {
64     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
65     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
66     0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
67     0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
68     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
69     0x0028, 0x0029, 0x002a, 0x2192, 0x2190, 0x2191, 0x2193, 0x002f,
70     0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
71     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
72     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
73     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
74     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
75     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
76     0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
77     0x2591, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
78     0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
79     0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
80     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
81     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
82     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
83     0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
84     0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
85     0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
86     0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
87     0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
88     0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
89     0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
90     0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
91     0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
92     0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
93     0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
94     0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
95     0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
96   },
97   /* IBM Codepage 437 mapped to Unicode */
98   {
99     0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, 
100     0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
101     0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
102     0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
103     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
104     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
105     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
106     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
107     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
108     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
109     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
110     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
111     0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
112     0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
113     0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
114     0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
115     0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
116     0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
117     0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
118     0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
119     0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
120     0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
121     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
122     0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
123     0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
124     0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
125     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
126     0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
127     0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
128     0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
129     0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
130     0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
131   }, 
132   /* User mapping -- default to codes for direct font mapping */
133   {
134     0xf000, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007,
135     0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f,
136     0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
137     0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
138     0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
139     0xf028, 0xf029, 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f,
140     0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
141     0xf038, 0xf039, 0xf03a, 0xf03b, 0xf03c, 0xf03d, 0xf03e, 0xf03f,
142     0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
143     0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f,
144     0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, 0xf056, 0xf057,
145     0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
146     0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067,
147     0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, 0xf06d, 0xf06e, 0xf06f,
148     0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
149     0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f,
150     0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
151     0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
152     0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
153     0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
154     0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6, 0xf0a7,
155     0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae, 0xf0af,
156     0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xf0b6, 0xf0b7,
157     0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be, 0xf0bf,
158     0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6, 0xf0c7,
159     0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb, 0xf0cc, 0xf0cd, 0xf0ce, 0xf0cf,
160     0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d7,
161     0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc, 0xf0dd, 0xf0de, 0xf0df,
162     0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
163     0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
164     0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
165     0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
166   }
167 };
168
169 /* The standard kernel character-to-font mappings are not invertible
170    -- this is just a best effort. */
171
172 #define MAX_GLYPH 512           /* Max possible glyph value */
173
174 static int inv_translate[MAX_NR_CONSOLES];
175
176 struct uni_pagedir {
177         u16             **uni_pgdir[32];
178         unsigned long   refcount;
179         unsigned long   sum;
180         unsigned char   *inverse_translations[4];
181         u16             *inverse_trans_unicode;
182 };
183
184 static struct uni_pagedir *dflt;
185
186 static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int i)
187 {
188         int j, glyph;
189         unsigned short *t = translations[i];
190         unsigned char *q;
191         
192         if (!p) return;
193         q = p->inverse_translations[i];
194
195         if (!q) {
196                 q = p->inverse_translations[i] = kmalloc(MAX_GLYPH, GFP_KERNEL);
197                 if (!q) return;
198         }
199         memset(q, 0, MAX_GLYPH);
200
201         for (j = 0; j < E_TABSZ; j++) {
202                 glyph = conv_uni_to_pc(conp, t[j]);
203                 if (glyph >= 0 && glyph < MAX_GLYPH && q[glyph] < 32) {
204                         /* prefer '-' above SHY etc. */
205                         q[glyph] = j;
206                 }
207         }
208 }
209
210 static void set_inverse_trans_unicode(struct vc_data *conp,
211                                       struct uni_pagedir *p)
212 {
213         int i, j, k, glyph;
214         u16 **p1, *p2;
215         u16 *q;
216
217         if (!p) return;
218         q = p->inverse_trans_unicode;
219         if (!q) {
220                 q = p->inverse_trans_unicode =
221                         kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL);
222                 if (!q)
223                         return;
224         }
225         memset(q, 0, MAX_GLYPH * sizeof(u16));
226
227         for (i = 0; i < 32; i++) {
228                 p1 = p->uni_pgdir[i];
229                 if (!p1)
230                         continue;
231                 for (j = 0; j < 32; j++) {
232                         p2 = p1[j];
233                         if (!p2)
234                                 continue;
235                         for (k = 0; k < 64; k++) {
236                                 glyph = p2[k];
237                                 if (glyph >= 0 && glyph < MAX_GLYPH
238                                                && q[glyph] < 32)
239                                         q[glyph] = (i << 11) + (j << 6) + k;
240                         }
241                 }
242         }
243 }
244
245 unsigned short *set_translate(int m, struct vc_data *vc)
246 {
247         inv_translate[vc->vc_num] = m;
248         return translations[m];
249 }
250
251 /*
252  * Inverse translation is impossible for several reasons:
253  * 1. The font<->character maps are not 1-1.
254  * 2. The text may have been written while a different translation map
255  *    was active.
256  * Still, it is now possible to a certain extent to cut and paste non-ASCII.
257  */
258 u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
259 {
260         struct uni_pagedir *p;
261         int m;
262         if (glyph < 0 || glyph >= MAX_GLYPH)
263                 return 0;
264         else {
265                 p = *conp->vc_uni_pagedir_loc;
266                 if (!p)
267                         return glyph;
268                 else if (use_unicode) {
269                         if (!p->inverse_trans_unicode)
270                                 return glyph;
271                         else
272                                 return p->inverse_trans_unicode[glyph];
273                         } else {
274                         m = inv_translate[conp->vc_num];
275                         if (!p->inverse_translations[m])
276                                 return glyph;
277                         else
278                                 return p->inverse_translations[m][glyph];
279                         }
280         }
281 }
282 EXPORT_SYMBOL_GPL(inverse_translate);
283
284 static void update_user_maps(void)
285 {
286         int i;
287         struct uni_pagedir *p, *q = NULL;
288         
289         for (i = 0; i < MAX_NR_CONSOLES; i++) {
290                 if (!vc_cons_allocated(i))
291                         continue;
292                 p = *vc_cons[i].d->vc_uni_pagedir_loc;
293                 if (p && p != q) {
294                         set_inverse_transl(vc_cons[i].d, p, USER_MAP);
295                         set_inverse_trans_unicode(vc_cons[i].d, p);
296                         q = p;
297                 }
298         }
299 }
300
301 /*
302  * Load customizable translation table
303  * arg points to a 256 byte translation table.
304  *
305  * The "old" variants are for translation directly to font (using the
306  * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
307  * Unicodes explicitly.
308  */
309 int con_set_trans_old(unsigned char __user * arg)
310 {
311         int i;
312         unsigned short *p = translations[USER_MAP];
313
314         if (!access_ok(VERIFY_READ, arg, E_TABSZ))
315                 return -EFAULT;
316
317         console_lock();
318         for (i=0; i<E_TABSZ ; i++) {
319                 unsigned char uc;
320                 __get_user(uc, arg+i);
321                 p[i] = UNI_DIRECT_BASE | uc;
322         }
323
324         update_user_maps();
325         console_unlock();
326         return 0;
327 }
328
329 int con_get_trans_old(unsigned char __user * arg)
330 {
331         int i, ch;
332         unsigned short *p = translations[USER_MAP];
333
334         if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
335                 return -EFAULT;
336
337         console_lock();
338         for (i=0; i<E_TABSZ ; i++)
339         {
340                 ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
341                 __put_user((ch & ~0xff) ? 0 : ch, arg+i);
342         }
343         console_unlock();
344         return 0;
345 }
346
347 int con_set_trans_new(ushort __user * arg)
348 {
349         int i;
350         unsigned short *p = translations[USER_MAP];
351
352         if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
353                 return -EFAULT;
354
355         console_lock();
356         for (i=0; i<E_TABSZ ; i++) {
357                 unsigned short us;
358                 __get_user(us, arg+i);
359                 p[i] = us;
360         }
361
362         update_user_maps();
363         console_unlock();
364         return 0;
365 }
366
367 int con_get_trans_new(ushort __user * arg)
368 {
369         int i;
370         unsigned short *p = translations[USER_MAP];
371
372         if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
373                 return -EFAULT;
374
375         console_lock();
376         for (i=0; i<E_TABSZ ; i++)
377           __put_user(p[i], arg+i);
378         console_unlock();
379         
380         return 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 << 20U) + 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
540         if (!ct)
541                 return 0;
542
543         console_lock();
544
545         /* Save original vc_unipagdir_loc in case we allocate a new one */
546         p = *vc->vc_uni_pagedir_loc;
547
548         if (!p) {
549                 err = -EINVAL;
550
551                 goto out_unlock;
552         }
553         
554         if (p->refcount > 1) {
555                 int j, k;
556                 u16 **p1, *p2, l;
557                 
558                 err1 = con_do_clear_unimap(vc);
559                 if (err1) {
560                         console_unlock();
561                         return err1;
562                 }
563                 
564                 /*
565                  * Since refcount was > 1, con_clear_unimap() allocated a
566                  * a new uni_pagedir for this vc.  Re: p != q
567                  */
568                 q = *vc->vc_uni_pagedir_loc;
569
570                 /*
571                  * uni_pgdir is a 32*32*64 table with rows allocated
572                  * when its first entry is added.  The unicode value must
573                  * still be incremented for empty rows.  We are copying
574                  * entries from "p" (old) to "q" (new).
575                  */
576                 l = 0;          /* unicode value */
577                 for (i = 0; i < 32; i++) {
578                 p1 = p->uni_pgdir[i];
579                 if (p1)
580                         for (j = 0; j < 32; j++) {
581                         p2 = p1[j];
582                         if (p2) {
583                                 for (k = 0; k < 64; k++, l++)
584                                 if (p2[k] != 0xffff) {
585                                         /*
586                                          * Found one, copy entry for unicode
587                                          * l with fontpos value p2[k].
588                                          */
589                                         err1 = con_insert_unipair(q, l, p2[k]);
590                                         if (err1) {
591                                                 p->refcount++;
592                                                 *vc->vc_uni_pagedir_loc = p;
593                                                 con_release_unimap(q);
594                                                 kfree(q);
595                                                 console_unlock();
596                                                 return err1; 
597                                         }
598                                 }
599                         } else {
600                                 /* Account for row of 64 empty entries */
601                                 l += 64;
602                         }
603                 }
604                 else
605                         /* Account for empty table */
606                         l += 32 * 64;
607                 }
608
609                 /*
610                  * Finished copying font table, set vc_uni_pagedir to new table
611                  */
612                 p = q;
613         } else if (p == dflt) {
614                 dflt = NULL;
615         }
616
617         /*
618          * Insert user specified unicode pairs into new table.
619          */
620         while (ct--) {
621                 unsigned short unicode, fontpos;
622                 __get_user(unicode, &list->unicode);
623                 __get_user(fontpos, &list->fontpos);
624                 if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
625                         err = err1;
626                 list++;
627         }
628         
629         /*
630          * Merge with fontmaps of any other virtual consoles.
631          */
632         if (con_unify_unimap(vc, p)) {
633                 console_unlock();
634                 return err;
635         }
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         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, ect;
739         u16 **p1, *p2;
740         struct uni_pagedir *p;
741
742         console_lock();
743
744         ect = 0;
745         if (*vc->vc_uni_pagedir_loc) {
746                 p = *vc->vc_uni_pagedir_loc;
747                 for (i = 0; i < 32; i++) {
748                 p1 = p->uni_pgdir[i];
749                 if (p1)
750                         for (j = 0; j < 32; j++) {
751                         p2 = *(p1++);
752                         if (p2)
753                                 for (k = 0; k < 64; k++) {
754                                         if (*p2 < MAX_GLYPH && ect++ < ct) {
755                                                 __put_user((u_short)((i<<11)+(j<<6)+k),
756                                                            &list->unicode);
757                                                 __put_user((u_short) *p2, 
758                                                            &list->fontpos);
759                                                 list++;
760                                         }
761                                         p2++;
762                                 }
763                         }
764                 }
765         }
766         __put_user(ect, uct);
767         console_unlock();
768         return ((ect <= ct) ? 0 : -ENOMEM);
769 }
770
771 /*
772  * Always use USER_MAP. These functions are used by the keyboard,
773  * which shouldn't be affected by G0/G1 switching, etc.
774  * If the user map still contains default values, i.e. the
775  * direct-to-font mapping, then assume user is using Latin1.
776  *
777  * FIXME: at some point we need to decide if we want to lock the table
778  * update element itself via the keyboard_event_lock for consistency with the
779  * keyboard driver as well as the consoles
780  */
781 /* may be called during an interrupt */
782 u32 conv_8bit_to_uni(unsigned char c)
783 {
784         unsigned short uni = translations[USER_MAP][c];
785         return uni == (0xf000 | c) ? c : uni;
786 }
787
788 int conv_uni_to_8bit(u32 uni)
789 {
790         int c;
791         for (c = 0; c < 0x100; c++)
792                 if (translations[USER_MAP][c] == uni ||
793                    (translations[USER_MAP][c] == (c | 0xf000) && uni == c))
794                         return c;
795         return -1;
796 }
797
798 int
799 conv_uni_to_pc(struct vc_data *conp, long ucs) 
800 {
801         int h;
802         u16 **p1, *p2;
803         struct uni_pagedir *p;
804   
805         /* Only 16-bit codes supported at this time */
806         if (ucs > 0xffff)
807                 return -4;              /* Not found */
808         else if (ucs < 0x20)
809                 return -1;              /* Not a printable character */
810         else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
811                 return -2;                      /* Zero-width space */
812         /*
813          * UNI_DIRECT_BASE indicates the start of the region in the User Zone
814          * which always has a 1:1 mapping to the currently loaded font.  The
815          * UNI_DIRECT_MASK indicates the bit span of the region.
816          */
817         else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
818                 return ucs & UNI_DIRECT_MASK;
819   
820         if (!*conp->vc_uni_pagedir_loc)
821                 return -3;
822
823         p = *conp->vc_uni_pagedir_loc;
824         if ((p1 = p->uni_pgdir[ucs >> 11]) &&
825             (p2 = p1[(ucs >> 6) & 0x1f]) &&
826             (h = p2[ucs & 0x3f]) < MAX_GLYPH)
827                 return h;
828
829         return -4;              /* not found */
830 }
831
832 /*
833  * This is called at sys_setup time, after memory and the console are
834  * initialized.  It must be possible to call kmalloc(..., GFP_KERNEL)
835  * from this function, hence the call from sys_setup.
836  */
837 void __init 
838 console_map_init(void)
839 {
840         int i;
841         
842         for (i = 0; i < MAX_NR_CONSOLES; i++)
843                 if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
844                         con_set_default_unimap(vc_cons[i].d);
845 }
846