1
2
3
4
5
6
7
8
9
10
11
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/consolemap.h>
23#include <linux/vt_kern.h>
24
25static unsigned short translations[][256] = {
26
27 {
28 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
29 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
30 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
31 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
32 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
33 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
34 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
35 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
36 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
37 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
38 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
39 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
40 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
41 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
42 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
43 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
44 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
45 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
46 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
47 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
48 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
49 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
50 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
51 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
52 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
53 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
54 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
55 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
56 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
57 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
58 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
59 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
60 },
61
62 {
63 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
64 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
65 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
66 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
67 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
68 0x0028, 0x0029, 0x002a, 0x2192, 0x2190, 0x2191, 0x2193, 0x002f,
69 0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
70 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
71 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
72 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
73 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
74 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
75 0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
76 0x2591, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
77 0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
78 0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
79 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
80 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
81 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
82 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
83 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
84 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
85 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
86 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
87 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
88 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
89 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
90 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
91 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
92 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
93 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
94 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
95 },
96
97 {
98 0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
99 0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
100 0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
101 0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
102 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
103 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
104 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
105 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
106 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
107 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
108 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
109 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
110 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
111 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
112 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
113 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
114 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
115 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
116 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
117 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
118 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
119 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
120 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
121 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
122 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
123 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
124 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
125 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
126 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
127 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
128 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
129 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
130 },
131
132 {
133 0xf000, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007,
134 0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f,
135 0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
136 0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
137 0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
138 0xf028, 0xf029, 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f,
139 0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
140 0xf038, 0xf039, 0xf03a, 0xf03b, 0xf03c, 0xf03d, 0xf03e, 0xf03f,
141 0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
142 0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f,
143 0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, 0xf056, 0xf057,
144 0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
145 0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067,
146 0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, 0xf06d, 0xf06e, 0xf06f,
147 0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
148 0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f,
149 0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
150 0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
151 0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
152 0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
153 0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6, 0xf0a7,
154 0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae, 0xf0af,
155 0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xf0b6, 0xf0b7,
156 0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be, 0xf0bf,
157 0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6, 0xf0c7,
158 0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb, 0xf0cc, 0xf0cd, 0xf0ce, 0xf0cf,
159 0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d7,
160 0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc, 0xf0dd, 0xf0de, 0xf0df,
161 0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
162 0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
163 0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
164 0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
165 }
166};
167
168
169
170
171#define MAX_GLYPH 512
172
173static int inv_translate[MAX_NR_CONSOLES];
174
175struct uni_pagedir {
176 u16 **uni_pgdir[32];
177 unsigned long refcount;
178 unsigned long sum;
179 unsigned char *inverse_translations[4];
180 int readonly;
181};
182
183static struct uni_pagedir *dflt;
184
185static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int i)
186{
187 int j, glyph;
188 unsigned short *t = translations[i];
189 unsigned char *q;
190
191 if (!p) return;
192 q = p->inverse_translations[i];
193
194 if (!q) {
195 q = p->inverse_translations[i] = (unsigned char *)
196 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
205 q[glyph] = j;
206 }
207 }
208}
209
210unsigned short *set_translate(int m, struct vc_data *vc)
211{
212 inv_translate[vc->vc_num] = m;
213 return translations[m];
214}
215
216
217
218
219
220
221
222
223unsigned char inverse_translate(struct vc_data *conp, int glyph)
224{
225 struct uni_pagedir *p;
226 if (glyph < 0 || glyph >= MAX_GLYPH)
227 return 0;
228 else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) ||
229 !p->inverse_translations[inv_translate[conp->vc_num]])
230 return glyph;
231 else
232 return p->inverse_translations[inv_translate[conp->vc_num]][glyph];
233}
234
235static void update_user_maps(void)
236{
237 int i;
238 struct uni_pagedir *p, *q = NULL;
239
240 for (i = 0; i < MAX_NR_CONSOLES; i++) {
241 if (!vc_cons_allocated(i))
242 continue;
243 p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
244 if (p && p != q) {
245 set_inverse_transl(vc_cons[i].d, p, USER_MAP);
246 q = p;
247 }
248 }
249}
250
251
252
253
254
255
256
257
258
259int con_set_trans_old(unsigned char __user * arg)
260{
261 int i;
262 unsigned short *p = translations[USER_MAP];
263
264 if (!access_ok(VERIFY_READ, arg, E_TABSZ))
265 return -EFAULT;
266
267 for (i=0; i<E_TABSZ ; i++) {
268 unsigned char uc;
269 __get_user(uc, arg+i);
270 p[i] = UNI_DIRECT_BASE | uc;
271 }
272
273 update_user_maps();
274 return 0;
275}
276
277int con_get_trans_old(unsigned char __user * arg)
278{
279 int i, ch;
280 unsigned short *p = translations[USER_MAP];
281
282 if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
283 return -EFAULT;
284
285 for (i=0; i<E_TABSZ ; i++)
286 {
287 ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
288 __put_user((ch & ~0xff) ? 0 : ch, arg+i);
289 }
290 return 0;
291}
292
293int con_set_trans_new(ushort __user * arg)
294{
295 int i;
296 unsigned short *p = translations[USER_MAP];
297
298 if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
299 return -EFAULT;
300
301 for (i=0; i<E_TABSZ ; i++) {
302 unsigned short us;
303 __get_user(us, arg+i);
304 p[i] = us;
305 }
306
307 update_user_maps();
308 return 0;
309}
310
311int con_get_trans_new(ushort __user * arg)
312{
313 int i;
314 unsigned short *p = translations[USER_MAP];
315
316 if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
317 return -EFAULT;
318
319 for (i=0; i<E_TABSZ ; i++)
320 __put_user(p[i], arg+i);
321
322 return 0;
323}
324
325
326
327
328
329
330
331
332
333
334
335extern u8 dfont_unicount[];
336extern u16 dfont_unitable[];
337
338static void con_release_unimap(struct uni_pagedir *p)
339{
340 u16 **p1;
341 int i, j;
342
343 if (p == dflt) dflt = NULL;
344 for (i = 0; i < 32; i++) {
345 if ((p1 = p->uni_pgdir[i]) != NULL) {
346 for (j = 0; j < 32; j++)
347 kfree(p1[j]);
348 kfree(p1);
349 }
350 p->uni_pgdir[i] = NULL;
351 }
352 for (i = 0; i < 4; i++) {
353 kfree(p->inverse_translations[i]);
354 p->inverse_translations[i] = NULL;
355 }
356}
357
358void con_free_unimap(struct vc_data *vc)
359{
360 struct uni_pagedir *p;
361
362 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
363 if (!p)
364 return;
365 *vc->vc_uni_pagedir_loc = 0;
366 if (--p->refcount)
367 return;
368 con_release_unimap(p);
369 kfree(p);
370}
371
372static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
373{
374 int i, j, k;
375 struct uni_pagedir *q;
376
377 for (i = 0; i < MAX_NR_CONSOLES; i++) {
378 if (!vc_cons_allocated(i))
379 continue;
380 q = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
381 if (!q || q == p || q->sum != p->sum)
382 continue;
383 for (j = 0; j < 32; j++) {
384 u16 **p1, **q1;
385 p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
386 if (!p1 && !q1)
387 continue;
388 if (!p1 || !q1)
389 break;
390 for (k = 0; k < 32; k++) {
391 if (!p1[k] && !q1[k])
392 continue;
393 if (!p1[k] || !q1[k])
394 break;
395 if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
396 break;
397 }
398 if (k < 32)
399 break;
400 }
401 if (j == 32) {
402 q->refcount++;
403 *conp->vc_uni_pagedir_loc = (unsigned long)q;
404 con_release_unimap(p);
405 kfree(p);
406 return 1;
407 }
408 }
409 return 0;
410}
411
412static int
413con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
414{
415 int i, n;
416 u16 **p1, *p2;
417
418 if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
419 p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
420 if (!p1) return -ENOMEM;
421 for (i = 0; i < 32; i++)
422 p1[i] = NULL;
423 }
424
425 if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
426 p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
427 if (!p2) return -ENOMEM;
428 memset(p2, 0xff, 64*sizeof(u16));
429 }
430
431 p2[unicode & 0x3f] = fontpos;
432
433 p->sum += (fontpos << 20) + unicode;
434
435 return 0;
436}
437
438
439int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
440{
441 struct uni_pagedir *p, *q;
442
443 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
444 if (p && p->readonly) return -EIO;
445 if (!p || --p->refcount) {
446 q = (struct uni_pagedir *)kmalloc(sizeof(*p), GFP_KERNEL);
447 if (!q) {
448 if (p) p->refcount++;
449 return -ENOMEM;
450 }
451 memset(q, 0, sizeof(*q));
452 q->refcount=1;
453 *vc->vc_uni_pagedir_loc = (unsigned long)q;
454 } else {
455 if (p == dflt) dflt = NULL;
456 p->refcount++;
457 p->sum = 0;
458 con_release_unimap(p);
459 }
460 return 0;
461}
462
463int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
464{
465 int err = 0, err1, i;
466 struct uni_pagedir *p, *q;
467
468 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
469 if (p->readonly) return -EIO;
470
471 if (!ct) return 0;
472
473 if (p->refcount > 1) {
474 int j, k;
475 u16 **p1, *p2, l;
476
477 err1 = con_clear_unimap(vc, NULL);
478 if (err1) return err1;
479
480 q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
481 for (i = 0, l = 0; i < 32; i++)
482 if ((p1 = p->uni_pgdir[i]))
483 for (j = 0; j < 32; j++)
484 if ((p2 = p1[j]))
485 for (k = 0; k < 64; k++, l++)
486 if (p2[k] != 0xffff) {
487 err1 = con_insert_unipair(q, l, p2[k]);
488 if (err1) {
489 p->refcount++;
490 *vc->vc_uni_pagedir_loc = (unsigned long)p;
491 con_release_unimap(q);
492 kfree(q);
493 return err1;
494 }
495 }
496 p = q;
497 } else if (p == dflt)
498 dflt = NULL;
499
500 while (ct--) {
501 unsigned short unicode, fontpos;
502 __get_user(unicode, &list->unicode);
503 __get_user(fontpos, &list->fontpos);
504 if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
505 err = err1;
506 list++;
507 }
508
509 if (con_unify_unimap(vc, p))
510 return err;
511
512 for (i = 0; i <= 3; i++)
513 set_inverse_transl(vc, p, i);
514
515 return err;
516}
517
518
519
520
521
522
523int con_set_default_unimap(struct vc_data *vc)
524{
525 int i, j, err = 0, err1;
526 u16 *q;
527 struct uni_pagedir *p;
528
529 if (dflt) {
530 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
531 if (p == dflt)
532 return 0;
533 dflt->refcount++;
534 *vc->vc_uni_pagedir_loc = (unsigned long)dflt;
535 if (p && --p->refcount) {
536 con_release_unimap(p);
537 kfree(p);
538 }
539 return 0;
540 }
541
542
543
544 err = con_clear_unimap(vc, NULL);
545 if (err) return err;
546
547 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
548 q = dfont_unitable;
549
550 for (i = 0; i < 256; i++)
551 for (j = dfont_unicount[i]; j; j--) {
552 err1 = con_insert_unipair(p, *(q++), i);
553 if (err1)
554 err = err1;
555 }
556
557 if (con_unify_unimap(vc, p)) {
558 dflt = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
559 return err;
560 }
561
562 for (i = 0; i <= 3; i++)
563 set_inverse_transl(vc, p, i);
564 dflt = p;
565 return err;
566}
567EXPORT_SYMBOL(con_set_default_unimap);
568
569int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
570{
571 struct uni_pagedir *q;
572
573 if (!*src_vc->vc_uni_pagedir_loc)
574 return -EINVAL;
575 if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
576 return 0;
577 con_free_unimap(dst_vc);
578 q = (struct uni_pagedir *)*src_vc->vc_uni_pagedir_loc;
579 q->refcount++;
580 *dst_vc->vc_uni_pagedir_loc = (long)q;
581 return 0;
582}
583
584int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
585{
586 int i, j, k, ect;
587 u16 **p1, *p2;
588 struct uni_pagedir *p;
589
590 ect = 0;
591 if (*vc->vc_uni_pagedir_loc) {
592 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
593 for (i = 0; i < 32; i++)
594 if ((p1 = p->uni_pgdir[i]))
595 for (j = 0; j < 32; j++)
596 if ((p2 = *(p1++)))
597 for (k = 0; k < 64; k++) {
598 if (*p2 < MAX_GLYPH && ect++ < ct) {
599 __put_user((u_short)((i<<11)+(j<<6)+k),
600 &list->unicode);
601 __put_user((u_short) *p2,
602 &list->fontpos);
603 list++;
604 }
605 p2++;
606 }
607 }
608 __put_user(ect, uct);
609 return ((ect <= ct) ? 0 : -ENOMEM);
610}
611
612void con_protect_unimap(struct vc_data *vc, int rdonly)
613{
614 struct uni_pagedir *p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
615
616 if (p)
617 p->readonly = rdonly;
618}
619
620int
621conv_uni_to_pc(struct vc_data *conp, long ucs)
622{
623 int h;
624 u16 **p1, *p2;
625 struct uni_pagedir *p;
626
627
628 if (ucs > 0xffff)
629 ucs = 0xfffd;
630 else if (ucs < 0x20 || ucs >= 0xfffe)
631 return -1;
632 else if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f))
633 return -2;
634
635
636
637
638
639 else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
640 return ucs & UNI_DIRECT_MASK;
641
642 if (!*conp->vc_uni_pagedir_loc)
643 return -3;
644
645 p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
646 if ((p1 = p->uni_pgdir[ucs >> 11]) &&
647 (p2 = p1[(ucs >> 6) & 0x1f]) &&
648 (h = p2[ucs & 0x3f]) < MAX_GLYPH)
649 return h;
650
651 return -4;
652}
653
654
655
656
657
658
659void __init
660console_map_init(void)
661{
662 int i;
663
664 for (i = 0; i < MAX_NR_CONSOLES; i++)
665 if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
666 con_set_default_unimap(vc_cons[i].d);
667}
668
669EXPORT_SYMBOL(con_copy_unimap);
670