Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
consolemap.c
Go to the documentation of this file.
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 <[email protected]>, July 1998
10  *
11  * Fix bug in inverse translation. Stanislav Voronyi <[email protected]>, 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];
182  int readonly;
183 };
184 
185 static struct uni_pagedir *dflt;
186 
187 static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int i)
188 {
189  int j, glyph;
190  unsigned short *t = translations[i];
191  unsigned char *q;
192 
193  if (!p) return;
194  q = p->inverse_translations[i];
195 
196  if (!q) {
197  q = p->inverse_translations[i] = (unsigned char *)
199  if (!q) return;
200  }
201  memset(q, 0, MAX_GLYPH);
202 
203  for (j = 0; j < E_TABSZ; j++) {
204  glyph = conv_uni_to_pc(conp, t[j]);
205  if (glyph >= 0 && glyph < MAX_GLYPH && q[glyph] < 32) {
206  /* prefer '-' above SHY etc. */
207  q[glyph] = j;
208  }
209  }
210 }
211 
212 static void set_inverse_trans_unicode(struct vc_data *conp,
213  struct uni_pagedir *p)
214 {
215  int i, j, k, glyph;
216  u16 **p1, *p2;
217  u16 *q;
218 
219  if (!p) return;
220  q = p->inverse_trans_unicode;
221  if (!q) {
222  q = p->inverse_trans_unicode =
223  kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL);
224  if (!q)
225  return;
226  }
227  memset(q, 0, MAX_GLYPH * sizeof(u16));
228 
229  for (i = 0; i < 32; i++) {
230  p1 = p->uni_pgdir[i];
231  if (!p1)
232  continue;
233  for (j = 0; j < 32; j++) {
234  p2 = p1[j];
235  if (!p2)
236  continue;
237  for (k = 0; k < 64; k++) {
238  glyph = p2[k];
239  if (glyph >= 0 && glyph < MAX_GLYPH
240  && q[glyph] < 32)
241  q[glyph] = (i << 11) + (j << 6) + k;
242  }
243  }
244  }
245 }
246 
247 unsigned short *set_translate(int m, struct vc_data *vc)
248 {
249  inv_translate[vc->vc_num] = m;
250  return translations[m];
251 }
252 
253 /*
254  * Inverse translation is impossible for several reasons:
255  * 1. The font<->character maps are not 1-1.
256  * 2. The text may have been written while a different translation map
257  * was active.
258  * Still, it is now possible to a certain extent to cut and paste non-ASCII.
259  */
260 u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
261 {
262  struct uni_pagedir *p;
263  int m;
264  if (glyph < 0 || glyph >= MAX_GLYPH)
265  return 0;
266  else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc))
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 }
282 
283 static void update_user_maps(void)
284 {
285  int i;
286  struct uni_pagedir *p, *q = NULL;
287 
288  for (i = 0; i < MAX_NR_CONSOLES; i++) {
289  if (!vc_cons_allocated(i))
290  continue;
291  p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
292  if (p && p != q) {
293  set_inverse_transl(vc_cons[i].d, p, USER_MAP);
294  set_inverse_trans_unicode(vc_cons[i].d, p);
295  q = p;
296  }
297  }
298 }
299 
300 /*
301  * Load customizable translation table
302  * arg points to a 256 byte translation table.
303  *
304  * The "old" variants are for translation directly to font (using the
305  * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
306  * Unicodes explicitly.
307  */
308 int con_set_trans_old(unsigned char __user * arg)
309 {
310  int i;
311  unsigned short *p = translations[USER_MAP];
312 
313  if (!access_ok(VERIFY_READ, arg, E_TABSZ))
314  return -EFAULT;
315 
316  console_lock();
317  for (i=0; i<E_TABSZ ; i++) {
318  unsigned char uc;
319  __get_user(uc, arg+i);
320  p[i] = UNI_DIRECT_BASE | uc;
321  }
322 
323  update_user_maps();
324  console_unlock();
325  return 0;
326 }
327 
328 int con_get_trans_old(unsigned char __user * arg)
329 {
330  int i, ch;
331  unsigned short *p = translations[USER_MAP];
332 
333  if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
334  return -EFAULT;
335 
336  console_lock();
337  for (i=0; i<E_TABSZ ; i++)
338  {
339  ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
340  __put_user((ch & ~0xff) ? 0 : ch, arg+i);
341  }
342  console_unlock();
343  return 0;
344 }
345 
347 {
348  int i;
349  unsigned short *p = translations[USER_MAP];
350 
351  if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
352  return -EFAULT;
353 
354  console_lock();
355  for (i=0; i<E_TABSZ ; i++) {
356  unsigned short us;
357  __get_user(us, arg+i);
358  p[i] = us;
359  }
360 
361  update_user_maps();
362  console_unlock();
363  return 0;
364 }
365 
367 {
368  int i;
369  unsigned short *p = translations[USER_MAP];
370 
371  if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
372  return -EFAULT;
373 
374  console_lock();
375  for (i=0; i<E_TABSZ ; i++)
376  __put_user(p[i], arg+i);
377  console_unlock();
378 
379  return 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  if ((p1 = p->uni_pgdir[i]) != NULL) {
403  for (j = 0; j < 32; j++)
404  kfree(p1[j]);
405  kfree(p1);
406  }
407  p->uni_pgdir[i] = NULL;
408  }
409  for (i = 0; i < 4; i++) {
412  }
413  if (p->inverse_trans_unicode) {
416  }
417 }
418 
419 /* Caller must hold the console lock */
421 {
422  struct uni_pagedir *p;
423 
424  p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
425  if (!p)
426  return;
427  *vc->vc_uni_pagedir_loc = 0;
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 = (struct uni_pagedir *)*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 = (unsigned long)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  if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
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  if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
488  p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
489  if (!p2) return -ENOMEM;
490  memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
491  }
492 
493  p2[unicode & 0x3f] = fontpos;
494 
495  p->sum += (fontpos << 20) + unicode;
496 
497  return 0;
498 }
499 
500 /* ui is a leftover from using a hashtable, but might be used again
501  Caller must hold the lock */
502 static int con_do_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
503 {
504  struct uni_pagedir *p, *q;
505 
506  p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
507  if (p && p->readonly)
508  return -EIO;
509 
510  if (!p || --p->refcount) {
511  q = kzalloc(sizeof(*p), GFP_KERNEL);
512  if (!q) {
513  if (p)
514  p->refcount++;
515  return -ENOMEM;
516  }
517  q->refcount=1;
518  *vc->vc_uni_pagedir_loc = (unsigned long)q;
519  } else {
520  if (p == dflt) dflt = NULL;
521  p->refcount++;
522  p->sum = 0;
523  con_release_unimap(p);
524  }
525  return 0;
526 }
527 
528 int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
529 {
530  int ret;
531  console_lock();
532  ret = con_do_clear_unimap(vc, ui);
533  console_unlock();
534  return ret;
535 }
536 
537 int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
538 {
539  int err = 0, err1, i;
540  struct uni_pagedir *p, *q;
541 
542  console_lock();
543 
544  /* Save original vc_unipagdir_loc in case we allocate a new one */
545  p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
546  if (p->readonly) {
547  console_unlock();
548  return -EIO;
549  }
550 
551  if (!ct) {
552  console_unlock();
553  return 0;
554  }
555 
556  if (p->refcount > 1) {
557  int j, k;
558  u16 **p1, *p2, l;
559 
560  err1 = con_do_clear_unimap(vc, NULL);
561  if (err1) {
562  console_unlock();
563  return err1;
564  }
565 
566  /*
567  * Since refcount was > 1, con_clear_unimap() allocated a
568  * a new uni_pagedir for this vc. Re: p != q
569  */
570  q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
571 
572  /*
573  * uni_pgdir is a 32*32*64 table with rows allocated
574  * when its first entry is added. The unicode value must
575  * still be incremented for empty rows. We are copying
576  * entries from "p" (old) to "q" (new).
577  */
578  l = 0; /* unicode value */
579  for (i = 0; i < 32; i++)
580  if ((p1 = p->uni_pgdir[i]))
581  for (j = 0; j < 32; j++)
582  if ((p2 = p1[j])) {
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 = (unsigned long)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  else
604  /* Account for empty table */
605  l += 32 * 64;
606 
607  /*
608  * Finished copying font table, set vc_uni_pagedir to new table
609  */
610  p = q;
611  } else if (p == dflt) {
612  dflt = NULL;
613  }
614 
615  /*
616  * Insert user specified unicode pairs into new table.
617  */
618  while (ct--) {
619  unsigned short unicode, fontpos;
620  __get_user(unicode, &list->unicode);
621  __get_user(fontpos, &list->fontpos);
622  if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
623  err = err1;
624  list++;
625  }
626 
627  /*
628  * Merge with fontmaps of any other virtual consoles.
629  */
630  if (con_unify_unimap(vc, p)) {
631  console_unlock();
632  return err;
633  }
634 
635  for (i = 0; i <= 3; i++)
636  set_inverse_transl(vc, p, i); /* Update inverse translations */
637  set_inverse_trans_unicode(vc, p);
638 
639  console_unlock();
640  return err;
641 }
642 
655 {
656  int i, j, err = 0, err1;
657  u16 *q;
658  struct uni_pagedir *p;
659 
660  if (dflt) {
661  p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
662  if (p == dflt)
663  return 0;
664 
665  dflt->refcount++;
666  *vc->vc_uni_pagedir_loc = (unsigned long)dflt;
667  if (p && !--p->refcount) {
668  con_release_unimap(p);
669  kfree(p);
670  }
671  return 0;
672  }
673 
674  /* The default font is always 256 characters */
675 
676  err = con_do_clear_unimap(vc, NULL);
677  if (err)
678  return err;
679 
680  p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
681  q = dfont_unitable;
682 
683  for (i = 0; i < 256; i++)
684  for (j = dfont_unicount[i]; j; j--) {
685  err1 = con_insert_unipair(p, *(q++), i);
686  if (err1)
687  err = err1;
688  }
689 
690  if (con_unify_unimap(vc, p)) {
691  dflt = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
692  return err;
693  }
694 
695  for (i = 0; i <= 3; i++)
696  set_inverse_transl(vc, p, i); /* Update all inverse translations */
697  set_inverse_trans_unicode(vc, p);
698  dflt = p;
699  return err;
700 }
702 
710 int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
711 {
712  struct uni_pagedir *q;
713 
714  if (!*src_vc->vc_uni_pagedir_loc)
715  return -EINVAL;
716  if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
717  return 0;
718  con_free_unimap(dst_vc);
719  q = (struct uni_pagedir *)*src_vc->vc_uni_pagedir_loc;
720  q->refcount++;
721  *dst_vc->vc_uni_pagedir_loc = (long)q;
722  return 0;
723 }
725 
733 int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
734 {
735  int i, j, k, ect;
736  u16 **p1, *p2;
737  struct uni_pagedir *p;
738 
739  console_lock();
740 
741  ect = 0;
742  if (*vc->vc_uni_pagedir_loc) {
743  p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
744  for (i = 0; i < 32; i++)
745  if ((p1 = p->uni_pgdir[i]))
746  for (j = 0; j < 32; j++)
747  if ((p2 = *(p1++)))
748  for (k = 0; k < 64; k++) {
749  if (*p2 < MAX_GLYPH && ect++ < ct) {
750  __put_user((u_short)((i<<11)+(j<<6)+k),
751  &list->unicode);
752  __put_user((u_short) *p2,
753  &list->fontpos);
754  list++;
755  }
756  p2++;
757  }
758  }
759  __put_user(ect, uct);
760  console_unlock();
761  return ((ect <= ct) ? 0 : -ENOMEM);
762 }
763 
764 /*
765  * Always use USER_MAP. These functions are used by the keyboard,
766  * which shouldn't be affected by G0/G1 switching, etc.
767  * If the user map still contains default values, i.e. the
768  * direct-to-font mapping, then assume user is using Latin1.
769  *
770  * FIXME: at some point we need to decide if we want to lock the table
771  * update element itself via the keyboard_event_lock for consistency with the
772  * keyboard driver as well as the consoles
773  */
774 /* may be called during an interrupt */
775 u32 conv_8bit_to_uni(unsigned char c)
776 {
777  unsigned short uni = translations[USER_MAP][c];
778  return uni == (0xf000 | c) ? c : uni;
779 }
780 
782 {
783  int c;
784  for (c = 0; c < 0x100; c++)
785  if (translations[USER_MAP][c] == uni ||
786  (translations[USER_MAP][c] == (c | 0xf000) && uni == c))
787  return c;
788  return -1;
789 }
790 
791 int
792 conv_uni_to_pc(struct vc_data *conp, long ucs)
793 {
794  int h;
795  u16 **p1, *p2;
796  struct uni_pagedir *p;
797 
798  /* Only 16-bit codes supported at this time */
799  if (ucs > 0xffff)
800  return -4; /* Not found */
801  else if (ucs < 0x20)
802  return -1; /* Not a printable character */
803  else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
804  return -2; /* Zero-width space */
805  /*
806  * UNI_DIRECT_BASE indicates the start of the region in the User Zone
807  * which always has a 1:1 mapping to the currently loaded font. The
808  * UNI_DIRECT_MASK indicates the bit span of the region.
809  */
810  else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
811  return ucs & UNI_DIRECT_MASK;
812 
813  if (!*conp->vc_uni_pagedir_loc)
814  return -3;
815 
816  p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
817  if ((p1 = p->uni_pgdir[ucs >> 11]) &&
818  (p2 = p1[(ucs >> 6) & 0x1f]) &&
819  (h = p2[ucs & 0x3f]) < MAX_GLYPH)
820  return h;
821 
822  return -4; /* not found */
823 }
824 
825 /*
826  * This is called at sys_setup time, after memory and the console are
827  * initialized. It must be possible to call kmalloc(..., GFP_KERNEL)
828  * from this function, hence the call from sys_setup.
829  */
830 void __init
832 {
833  int i;
834 
835  for (i = 0; i < MAX_NR_CONSOLES; i++)
836  if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
838 }
839