LCOV - code coverage report
Current view: top level - drivers/tty/vt - consolemap.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 11 283 3.9 %
Date: 2014-02-18 Functions: 3 23 13.0 %
Branches: 3 240 1.2 %

           Branch data     Line data    Source code
       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                 :            :         int             readonly;
     183                 :            : };
     184                 :            : 
     185                 :            : static struct uni_pagedir *dflt;
     186                 :            : 
     187                 :          0 : static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int i)
     188                 :            : {
     189                 :            :         int j, glyph;
     190                 :          0 :         unsigned short *t = translations[i];
     191                 :            :         unsigned char *q;
     192                 :            :         
     193         [ #  # ]:          0 :         if (!p) return;
     194                 :          0 :         q = p->inverse_translations[i];
     195                 :            : 
     196         [ #  # ]:          0 :         if (!q) {
     197                 :          0 :                 q = p->inverse_translations[i] = kmalloc(MAX_GLYPH, GFP_KERNEL);
     198         [ #  # ]:          0 :                 if (!q) return;
     199                 :            :         }
     200                 :          0 :         memset(q, 0, MAX_GLYPH);
     201                 :            : 
     202         [ #  # ]:          0 :         for (j = 0; j < E_TABSZ; j++) {
     203                 :          0 :                 glyph = conv_uni_to_pc(conp, t[j]);
     204 [ #  # ][ #  # ]:          0 :                 if (glyph >= 0 && glyph < MAX_GLYPH && q[glyph] < 32) {
     205                 :            :                         /* prefer '-' above SHY etc. */
     206                 :          0 :                         q[glyph] = j;
     207                 :            :                 }
     208                 :            :         }
     209                 :            : }
     210                 :            : 
     211                 :          0 : static void set_inverse_trans_unicode(struct vc_data *conp,
     212                 :            :                                       struct uni_pagedir *p)
     213                 :            : {
     214                 :            :         int i, j, k, glyph;
     215                 :            :         u16 **p1, *p2;
     216                 :            :         u16 *q;
     217                 :            : 
     218         [ #  # ]:          0 :         if (!p) return;
     219                 :          0 :         q = p->inverse_trans_unicode;
     220         [ #  # ]:          0 :         if (!q) {
     221                 :          0 :                 q = p->inverse_trans_unicode =
     222                 :            :                         kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL);
     223         [ #  # ]:          0 :                 if (!q)
     224                 :            :                         return;
     225                 :            :         }
     226                 :          0 :         memset(q, 0, MAX_GLYPH * sizeof(u16));
     227                 :            : 
     228         [ #  # ]:          0 :         for (i = 0; i < 32; i++) {
     229                 :          0 :                 p1 = p->uni_pgdir[i];
     230         [ #  # ]:          0 :                 if (!p1)
     231                 :          0 :                         continue;
     232         [ #  # ]:          0 :                 for (j = 0; j < 32; j++) {
     233                 :          0 :                         p2 = p1[j];
     234         [ #  # ]:          0 :                         if (!p2)
     235                 :          0 :                                 continue;
     236         [ #  # ]:          0 :                         for (k = 0; k < 64; k++) {
     237                 :          0 :                                 glyph = p2[k];
     238         [ #  # ]:          0 :                                 if (glyph >= 0 && glyph < MAX_GLYPH
     239         [ #  # ]:          0 :                                                && q[glyph] < 32)
     240                 :          0 :                                         q[glyph] = (i << 11) + (j << 6) + k;
     241                 :            :                         }
     242                 :            :                 }
     243                 :            :         }
     244                 :            : }
     245                 :            : 
     246                 :          0 : unsigned short *set_translate(int m, struct vc_data *vc)
     247                 :            : {
     248                 :         56 :         inv_translate[vc->vc_num] = m;
     249                 :         56 :         return translations[m];
     250                 :            : }
     251                 :            : 
     252                 :            : /*
     253                 :            :  * Inverse translation is impossible for several reasons:
     254                 :            :  * 1. The font<->character maps are not 1-1.
     255                 :            :  * 2. The text may have been written while a different translation map
     256                 :            :  *    was active.
     257                 :            :  * Still, it is now possible to a certain extent to cut and paste non-ASCII.
     258                 :            :  */
     259                 :          0 : u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
     260                 :            : {
     261                 :            :         struct uni_pagedir *p;
     262                 :            :         int m;
     263         [ #  # ]:          0 :         if (glyph < 0 || glyph >= MAX_GLYPH)
     264                 :            :                 return 0;
     265         [ #  # ]:          0 :         else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc))
     266                 :          0 :                 return glyph;
     267         [ #  # ]:          0 :         else if (use_unicode) {
     268         [ #  # ]:          0 :                 if (!p->inverse_trans_unicode)
     269                 :          0 :                         return glyph;
     270                 :            :                 else
     271                 :          0 :                         return p->inverse_trans_unicode[glyph];
     272                 :            :         } else {
     273                 :          0 :                 m = inv_translate[conp->vc_num];
     274         [ #  # ]:          0 :                 if (!p->inverse_translations[m])
     275                 :          0 :                         return glyph;
     276                 :            :                 else
     277                 :          0 :                         return p->inverse_translations[m][glyph];
     278                 :            :         }
     279                 :            : }
     280                 :            : EXPORT_SYMBOL_GPL(inverse_translate);
     281                 :            : 
     282                 :          0 : static void update_user_maps(void)
     283                 :            : {
     284                 :            :         int i;
     285                 :            :         struct uni_pagedir *p, *q = NULL;
     286                 :            :         
     287         [ #  # ]:          0 :         for (i = 0; i < MAX_NR_CONSOLES; i++) {
     288         [ #  # ]:          0 :                 if (!vc_cons_allocated(i))
     289                 :          0 :                         continue;
     290                 :          0 :                 p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
     291         [ #  # ]:          0 :                 if (p && p != q) {
     292                 :          0 :                         set_inverse_transl(vc_cons[i].d, p, USER_MAP);
     293                 :          0 :                         set_inverse_trans_unicode(vc_cons[i].d, p);
     294                 :            :                         q = p;
     295                 :            :                 }
     296                 :            :         }
     297                 :          0 : }
     298                 :            : 
     299                 :            : /*
     300                 :            :  * Load customizable translation table
     301                 :            :  * arg points to a 256 byte translation table.
     302                 :            :  *
     303                 :            :  * The "old" variants are for translation directly to font (using the
     304                 :            :  * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
     305                 :            :  * Unicodes explicitly.
     306                 :            :  */
     307                 :          0 : int con_set_trans_old(unsigned char __user * arg)
     308                 :            : {
     309                 :            :         int i;
     310                 :            :         unsigned short *p = translations[USER_MAP];
     311                 :            : 
     312         [ #  # ]:          0 :         if (!access_ok(VERIFY_READ, arg, E_TABSZ))
     313                 :            :                 return -EFAULT;
     314                 :            : 
     315                 :          0 :         console_lock();
     316         [ #  # ]:          0 :         for (i=0; i<E_TABSZ ; i++) {
     317                 :            :                 unsigned char uc;
     318                 :          0 :                 __get_user(uc, arg+i);
     319                 :          0 :                 p[i] = UNI_DIRECT_BASE | uc;
     320                 :            :         }
     321                 :            : 
     322                 :          0 :         update_user_maps();
     323                 :          0 :         console_unlock();
     324                 :          0 :         return 0;
     325                 :            : }
     326                 :            : 
     327                 :          0 : int con_get_trans_old(unsigned char __user * arg)
     328                 :            : {
     329                 :            :         int i, ch;
     330                 :            :         unsigned short *p = translations[USER_MAP];
     331                 :            : 
     332         [ #  # ]:          0 :         if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
     333                 :            :                 return -EFAULT;
     334                 :            : 
     335                 :          0 :         console_lock();
     336         [ #  # ]:          0 :         for (i=0; i<E_TABSZ ; i++)
     337                 :            :         {
     338                 :          0 :                 ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
     339         [ #  # ]:          0 :                 __put_user((ch & ~0xff) ? 0 : ch, arg+i);
     340                 :            :         }
     341                 :          0 :         console_unlock();
     342                 :          0 :         return 0;
     343                 :            : }
     344                 :            : 
     345                 :          0 : int con_set_trans_new(ushort __user * arg)
     346                 :            : {
     347                 :            :         int i;
     348                 :            :         unsigned short *p = translations[USER_MAP];
     349                 :            : 
     350         [ #  # ]:          0 :         if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
     351                 :            :                 return -EFAULT;
     352                 :            : 
     353                 :          0 :         console_lock();
     354         [ #  # ]:          0 :         for (i=0; i<E_TABSZ ; i++) {
     355                 :            :                 unsigned short us;
     356                 :          0 :                 __get_user(us, arg+i);
     357                 :          0 :                 p[i] = us;
     358                 :            :         }
     359                 :            : 
     360                 :          0 :         update_user_maps();
     361                 :          0 :         console_unlock();
     362                 :          0 :         return 0;
     363                 :            : }
     364                 :            : 
     365                 :          0 : int con_get_trans_new(ushort __user * arg)
     366                 :            : {
     367                 :            :         int i;
     368                 :            :         unsigned short *p = translations[USER_MAP];
     369                 :            : 
     370         [ #  # ]:          0 :         if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
     371                 :            :                 return -EFAULT;
     372                 :            : 
     373                 :          0 :         console_lock();
     374         [ #  # ]:          0 :         for (i=0; i<E_TABSZ ; i++)
     375                 :          0 :           __put_user(p[i], arg+i);
     376                 :          0 :         console_unlock();
     377                 :            :         
     378                 :          0 :         return 0;
     379                 :            : }
     380                 :            : 
     381                 :            : /*
     382                 :            :  * Unicode -> current font conversion 
     383                 :            :  *
     384                 :            :  * A font has at most 512 chars, usually 256.
     385                 :            :  * But one font position may represent several Unicode chars.
     386                 :            :  * A hashtable is somewhat of a pain to deal with, so use a
     387                 :            :  * "paged table" instead.  Simulation has shown the memory cost of
     388                 :            :  * this 3-level paged table scheme to be comparable to a hash table.
     389                 :            :  */
     390                 :            : 
     391                 :            : extern u8 dfont_unicount[];     /* Defined in console_defmap.c */
     392                 :            : extern u16 dfont_unitable[];
     393                 :            : 
     394                 :          0 : static void con_release_unimap(struct uni_pagedir *p)
     395                 :            : {
     396                 :            :         u16 **p1;
     397                 :            :         int i, j;
     398                 :            : 
     399         [ #  # ]:          0 :         if (p == dflt) dflt = NULL;  
     400         [ #  # ]:          0 :         for (i = 0; i < 32; i++) {
     401         [ #  # ]:          0 :                 if ((p1 = p->uni_pgdir[i]) != NULL) {
     402         [ #  # ]:          0 :                         for (j = 0; j < 32; j++)
     403                 :          0 :                                 kfree(p1[j]);
     404                 :          0 :                         kfree(p1);
     405                 :            :                 }
     406                 :          0 :                 p->uni_pgdir[i] = NULL;
     407                 :            :         }
     408         [ #  # ]:          0 :         for (i = 0; i < 4; i++) {
     409                 :          0 :                 kfree(p->inverse_translations[i]);
     410                 :          0 :                 p->inverse_translations[i] = NULL;
     411                 :            :         }
     412                 :          0 :         kfree(p->inverse_trans_unicode);
     413                 :          0 :         p->inverse_trans_unicode = NULL;
     414                 :          0 : }
     415                 :            : 
     416                 :            : /* Caller must hold the console lock */
     417                 :          0 : void con_free_unimap(struct vc_data *vc)
     418                 :            : {
     419                 :            :         struct uni_pagedir *p;
     420                 :            : 
     421                 :         56 :         p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
     422         [ -  + ]:         56 :         if (!p)
     423                 :            :                 return;
     424                 :          0 :         *vc->vc_uni_pagedir_loc = 0;
     425         [ #  # ]:          0 :         if (--p->refcount)
     426                 :            :                 return;
     427                 :          0 :         con_release_unimap(p);
     428                 :          0 :         kfree(p);
     429                 :            : }
     430                 :            :   
     431                 :          0 : static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
     432                 :            : {
     433                 :            :         int i, j, k;
     434                 :            :         struct uni_pagedir *q;
     435                 :            :         
     436         [ #  # ]:          0 :         for (i = 0; i < MAX_NR_CONSOLES; i++) {
     437         [ #  # ]:          0 :                 if (!vc_cons_allocated(i))
     438                 :          0 :                         continue;
     439                 :          0 :                 q = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
     440 [ #  # ][ #  # ]:          0 :                 if (!q || q == p || q->sum != p->sum)
     441                 :          0 :                         continue;
     442         [ #  # ]:          0 :                 for (j = 0; j < 32; j++) {
     443                 :            :                         u16 **p1, **q1;
     444                 :          0 :                         p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
     445         [ #  # ]:          0 :                         if (!p1 && !q1)
     446                 :          0 :                                 continue;
     447         [ #  # ]:          0 :                         if (!p1 || !q1)
     448                 :            :                                 break;
     449         [ #  # ]:          0 :                         for (k = 0; k < 32; k++) {
     450 [ #  # ][ #  # ]:          0 :                                 if (!p1[k] && !q1[k])
     451                 :          0 :                                         continue;
     452 [ #  # ][ #  # ]:          0 :                                 if (!p1[k] || !q1[k])
     453                 :            :                                         break;
     454         [ #  # ]:          0 :                                 if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
     455                 :            :                                         break;
     456                 :            :                         }
     457         [ #  # ]:          0 :                         if (k < 32)
     458                 :            :                                 break;
     459                 :            :                 }
     460         [ #  # ]:          0 :                 if (j == 32) {
     461                 :          0 :                         q->refcount++;
     462                 :          0 :                         *conp->vc_uni_pagedir_loc = (unsigned long)q;
     463                 :          0 :                         con_release_unimap(p);
     464                 :          0 :                         kfree(p);
     465                 :            :                         return 1;
     466                 :            :                 }
     467                 :            :         }
     468                 :            :         return 0;
     469                 :            : }
     470                 :            : 
     471                 :            : static int
     472                 :          0 : con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
     473                 :            : {
     474                 :            :         int i, n;
     475                 :            :         u16 **p1, *p2;
     476                 :            : 
     477         [ #  # ]:          0 :         if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
     478                 :          0 :                 p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
     479         [ #  # ]:          0 :                 if (!p1) return -ENOMEM;
     480         [ #  # ]:          0 :                 for (i = 0; i < 32; i++)
     481                 :          0 :                         p1[i] = NULL;
     482                 :            :         }
     483                 :            : 
     484         [ #  # ]:          0 :         if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
     485                 :          0 :                 p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
     486         [ #  # ]:          0 :                 if (!p2) return -ENOMEM;
     487                 :          0 :                 memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
     488                 :            :         }
     489                 :            : 
     490                 :          0 :         p2[unicode & 0x3f] = fontpos;
     491                 :            :         
     492                 :          0 :         p->sum += (fontpos << 20) + unicode;
     493                 :            : 
     494                 :          0 :         return 0;
     495                 :            : }
     496                 :            : 
     497                 :            : /* ui is a leftover from using a hashtable, but might be used again
     498                 :            :    Caller must hold the lock */
     499                 :          0 : static int con_do_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
     500                 :            : {
     501                 :            :         struct uni_pagedir *p, *q;
     502                 :            : 
     503                 :          0 :         p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
     504 [ #  # ][ #  # ]:          0 :         if (p && p->readonly)
     505                 :            :                 return -EIO;
     506                 :            : 
     507 [ #  # ][ #  # ]:          0 :         if (!p || --p->refcount) {
     508                 :            :                 q = kzalloc(sizeof(*p), GFP_KERNEL);
     509         [ #  # ]:          0 :                 if (!q) {
     510         [ #  # ]:          0 :                         if (p)
     511                 :          0 :                                 p->refcount++;
     512                 :            :                         return -ENOMEM;
     513                 :            :                 }
     514                 :          0 :                 q->refcount=1;
     515                 :          0 :                 *vc->vc_uni_pagedir_loc = (unsigned long)q;
     516                 :            :         } else {
     517         [ #  # ]:          0 :                 if (p == dflt) dflt = NULL;
     518                 :          0 :                 p->refcount++;
     519                 :          0 :                 p->sum = 0;
     520                 :          0 :                 con_release_unimap(p);
     521                 :            :         }
     522                 :            :         return 0;
     523                 :            : }
     524                 :            : 
     525                 :          0 : int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
     526                 :            : {
     527                 :            :         int ret;
     528                 :          0 :         console_lock();
     529                 :          0 :         ret = con_do_clear_unimap(vc, ui);
     530                 :          0 :         console_unlock();
     531                 :          0 :         return ret;
     532                 :            : }
     533                 :            :         
     534                 :          0 : int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
     535                 :            : {
     536                 :            :         int err = 0, err1, i;
     537                 :            :         struct uni_pagedir *p, *q;
     538                 :            : 
     539                 :          0 :         console_lock();
     540                 :            : 
     541                 :            :         /* Save original vc_unipagdir_loc in case we allocate a new one */
     542                 :          0 :         p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
     543         [ #  # ]:          0 :         if (p->readonly) {
     544                 :          0 :                 console_unlock();
     545                 :          0 :                 return -EIO;
     546                 :            :         }
     547                 :            :         
     548         [ #  # ]:          0 :         if (!ct) {
     549                 :          0 :                 console_unlock();
     550                 :          0 :                 return 0;
     551                 :            :         }
     552                 :            :         
     553         [ #  # ]:          0 :         if (p->refcount > 1) {
     554                 :            :                 int j, k;
     555                 :            :                 u16 **p1, *p2, l;
     556                 :            :                 
     557                 :          0 :                 err1 = con_do_clear_unimap(vc, NULL);
     558         [ #  # ]:          0 :                 if (err1) {
     559                 :          0 :                         console_unlock();
     560                 :          0 :                         return err1;
     561                 :            :                 }
     562                 :            :                 
     563                 :            :                 /*
     564                 :            :                  * Since refcount was > 1, con_clear_unimap() allocated a
     565                 :            :                  * a new uni_pagedir for this vc.  Re: p != q
     566                 :            :                  */
     567                 :          0 :                 q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
     568                 :            : 
     569                 :            :                 /*
     570                 :            :                  * uni_pgdir is a 32*32*64 table with rows allocated
     571                 :            :                  * when its first entry is added.  The unicode value must
     572                 :            :                  * still be incremented for empty rows.  We are copying
     573                 :            :                  * entries from "p" (old) to "q" (new).
     574                 :            :                  */
     575                 :            :                 l = 0;          /* unicode value */
     576         [ #  # ]:          0 :                 for (i = 0; i < 32; i++)
     577         [ #  # ]:          0 :                 if ((p1 = p->uni_pgdir[i]))
     578         [ #  # ]:          0 :                         for (j = 0; j < 32; j++)
     579         [ #  # ]:          0 :                         if ((p2 = p1[j])) {
     580         [ #  # ]:          0 :                                 for (k = 0; k < 64; k++, l++)
     581         [ #  # ]:          0 :                                 if (p2[k] != 0xffff) {
     582                 :            :                                         /*
     583                 :            :                                          * Found one, copy entry for unicode
     584                 :            :                                          * l with fontpos value p2[k].
     585                 :            :                                          */
     586                 :          0 :                                         err1 = con_insert_unipair(q, l, p2[k]);
     587         [ #  # ]:          0 :                                         if (err1) {
     588                 :          0 :                                                 p->refcount++;
     589                 :          0 :                                                 *vc->vc_uni_pagedir_loc = (unsigned long)p;
     590                 :          0 :                                                 con_release_unimap(q);
     591                 :          0 :                                                 kfree(q);
     592                 :          0 :                                                 console_unlock();
     593                 :          0 :                                                 return err1; 
     594                 :            :                                         }
     595                 :            :                                 }
     596                 :            :                         } else {
     597                 :            :                                 /* Account for row of 64 empty entries */
     598                 :          0 :                                 l += 64;
     599                 :            :                         }
     600                 :            :                 else
     601                 :            :                         /* Account for empty table */
     602                 :          0 :                         l += 32 * 64;
     603                 :            : 
     604                 :            :                 /*
     605                 :            :                  * Finished copying font table, set vc_uni_pagedir to new table
     606                 :            :                  */
     607                 :            :                 p = q;
     608         [ #  # ]:          0 :         } else if (p == dflt) {
     609                 :          0 :                 dflt = NULL;
     610                 :            :         }
     611                 :            : 
     612                 :            :         /*
     613                 :            :          * Insert user specified unicode pairs into new table.
     614                 :            :          */
     615         [ #  # ]:          0 :         while (ct--) {
     616                 :            :                 unsigned short unicode, fontpos;
     617                 :          0 :                 __get_user(unicode, &list->unicode);
     618                 :          0 :                 __get_user(fontpos, &list->fontpos);
     619         [ #  # ]:          0 :                 if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
     620                 :            :                         err = err1;
     621                 :          0 :                 list++;
     622                 :            :         }
     623                 :            :         
     624                 :            :         /*
     625                 :            :          * Merge with fontmaps of any other virtual consoles.
     626                 :            :          */
     627         [ #  # ]:          0 :         if (con_unify_unimap(vc, p)) {
     628                 :          0 :                 console_unlock();
     629                 :          0 :                 return err;
     630                 :            :         }
     631                 :            : 
     632         [ #  # ]:          0 :         for (i = 0; i <= 3; i++)
     633                 :          0 :                 set_inverse_transl(vc, p, i); /* Update inverse translations */
     634                 :          0 :         set_inverse_trans_unicode(vc, p);
     635                 :            : 
     636                 :          0 :         console_unlock();
     637                 :          0 :         return err;
     638                 :            : }
     639                 :            : 
     640                 :            : /**
     641                 :            :  *      con_set_default_unimap  -       set default unicode map
     642                 :            :  *      @vc: the console we are updating
     643                 :            :  *
     644                 :            :  *      Loads the unimap for the hardware font, as defined in uni_hash.tbl.
     645                 :            :  *      The representation used was the most compact I could come up
     646                 :            :  *      with.  This routine is executed at video setup, and when the
     647                 :            :  *      PIO_FONTRESET ioctl is called. 
     648                 :            :  *
     649                 :            :  *      The caller must hold the console lock
     650                 :            :  */
     651                 :          0 : int con_set_default_unimap(struct vc_data *vc)
     652                 :            : {
     653                 :            :         int i, j, err = 0, err1;
     654                 :            :         u16 *q;
     655                 :            :         struct uni_pagedir *p;
     656                 :            : 
     657         [ #  # ]:          0 :         if (dflt) {
     658                 :          0 :                 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
     659         [ #  # ]:          0 :                 if (p == dflt)
     660                 :            :                         return 0;
     661                 :            : 
     662                 :          0 :                 dflt->refcount++;
     663                 :          0 :                 *vc->vc_uni_pagedir_loc = (unsigned long)dflt;
     664 [ #  # ][ #  # ]:          0 :                 if (p && !--p->refcount) {
     665                 :          0 :                         con_release_unimap(p);
     666                 :          0 :                         kfree(p);
     667                 :            :                 }
     668                 :            :                 return 0;
     669                 :            :         }
     670                 :            :         
     671                 :            :         /* The default font is always 256 characters */
     672                 :            : 
     673                 :          0 :         err = con_do_clear_unimap(vc, NULL);
     674         [ #  # ]:          0 :         if (err)
     675                 :            :                 return err;
     676                 :            :     
     677                 :          0 :         p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
     678                 :            :         q = dfont_unitable;
     679                 :            :         
     680         [ #  # ]:          0 :         for (i = 0; i < 256; i++)
     681         [ #  # ]:          0 :                 for (j = dfont_unicount[i]; j; j--) {
     682                 :          0 :                         err1 = con_insert_unipair(p, *(q++), i);
     683         [ #  # ]:          0 :                         if (err1)
     684                 :            :                                 err = err1;
     685                 :            :                 }
     686                 :            :                         
     687         [ #  # ]:          0 :         if (con_unify_unimap(vc, p)) {
     688                 :          0 :                 dflt = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
     689                 :          0 :                 return err;
     690                 :            :         }
     691                 :            : 
     692         [ #  # ]:          0 :         for (i = 0; i <= 3; i++)
     693                 :          0 :                 set_inverse_transl(vc, p, i);   /* Update all inverse translations */
     694                 :          0 :         set_inverse_trans_unicode(vc, p);
     695                 :          0 :         dflt = p;
     696                 :          0 :         return err;
     697                 :            : }
     698                 :            : EXPORT_SYMBOL(con_set_default_unimap);
     699                 :            : 
     700                 :            : /**
     701                 :            :  *      con_copy_unimap         -       copy unimap between two vts
     702                 :            :  *      @dst_vc: target
     703                 :            :  *      @src_vt: source
     704                 :            :  *
     705                 :            :  *      The caller must hold the console lock when invoking this method
     706                 :            :  */
     707                 :          0 : int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
     708                 :            : {
     709                 :            :         struct uni_pagedir *q;
     710                 :            : 
     711         [ +  - ]:         56 :         if (!*src_vc->vc_uni_pagedir_loc)
     712                 :            :                 return -EINVAL;
     713         [ +  - ]:         56 :         if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
     714                 :            :                 return 0;
     715                 :         56 :         con_free_unimap(dst_vc);
     716                 :         56 :         q = (struct uni_pagedir *)*src_vc->vc_uni_pagedir_loc;
     717                 :         56 :         q->refcount++;
     718                 :         56 :         *dst_vc->vc_uni_pagedir_loc = (long)q;
     719                 :         56 :         return 0;
     720                 :            : }
     721                 :            : EXPORT_SYMBOL(con_copy_unimap);
     722                 :            : 
     723                 :            : /**
     724                 :            :  *      con_get_unimap          -       get the unicode map
     725                 :            :  *      @vc: the console to read from
     726                 :            :  *
     727                 :            :  *      Read the console unicode data for this console. Called from the ioctl
     728                 :            :  *      handlers.
     729                 :            :  */
     730                 :          0 : int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
     731                 :            : {
     732                 :            :         int i, j, k, ect;
     733                 :            :         u16 **p1, *p2;
     734                 :            :         struct uni_pagedir *p;
     735                 :            : 
     736                 :          0 :         console_lock();
     737                 :            : 
     738                 :            :         ect = 0;
     739         [ #  # ]:          0 :         if (*vc->vc_uni_pagedir_loc) {
     740                 :          0 :                 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
     741         [ #  # ]:          0 :                 for (i = 0; i < 32; i++)
     742         [ #  # ]:          0 :                 if ((p1 = p->uni_pgdir[i]))
     743         [ #  # ]:          0 :                         for (j = 0; j < 32; j++)
     744         [ #  # ]:          0 :                         if ((p2 = *(p1++)))
     745         [ #  # ]:          0 :                                 for (k = 0; k < 64; k++) {
     746 [ #  # ][ #  # ]:          0 :                                         if (*p2 < MAX_GLYPH && ect++ < ct) {
     747                 :          0 :                                                 __put_user((u_short)((i<<11)+(j<<6)+k),
     748                 :            :                                                            &list->unicode);
     749                 :          0 :                                                 __put_user((u_short) *p2, 
     750                 :            :                                                            &list->fontpos);
     751                 :          0 :                                                 list++;
     752                 :            :                                         }
     753                 :          0 :                                         p2++;
     754                 :            :                                 }
     755                 :            :         }
     756                 :          0 :         __put_user(ect, uct);
     757                 :          0 :         console_unlock();
     758         [ #  # ]:          0 :         return ((ect <= ct) ? 0 : -ENOMEM);
     759                 :            : }
     760                 :            : 
     761                 :            : /*
     762                 :            :  * Always use USER_MAP. These functions are used by the keyboard,
     763                 :            :  * which shouldn't be affected by G0/G1 switching, etc.
     764                 :            :  * If the user map still contains default values, i.e. the
     765                 :            :  * direct-to-font mapping, then assume user is using Latin1.
     766                 :            :  *
     767                 :            :  * FIXME: at some point we need to decide if we want to lock the table
     768                 :            :  * update element itself via the keyboard_event_lock for consistency with the
     769                 :            :  * keyboard driver as well as the consoles
     770                 :            :  */
     771                 :            : /* may be called during an interrupt */
     772                 :          0 : u32 conv_8bit_to_uni(unsigned char c)
     773                 :            : {
     774                 :          0 :         unsigned short uni = translations[USER_MAP][c];
     775         [ #  # ]:          0 :         return uni == (0xf000 | c) ? c : uni;
     776                 :            : }
     777                 :            : 
     778                 :          0 : int conv_uni_to_8bit(u32 uni)
     779                 :            : {
     780                 :            :         int c;
     781         [ #  # ]:          0 :         for (c = 0; c < 0x100; c++)
     782 [ #  # ][ #  # ]:          0 :                 if (translations[USER_MAP][c] == uni ||
     783         [ #  # ]:          0 :                    (translations[USER_MAP][c] == (c | 0xf000) && uni == c))
     784                 :            :                         return c;
     785                 :            :         return -1;
     786                 :            : }
     787                 :            : 
     788                 :            : int
     789                 :          0 : conv_uni_to_pc(struct vc_data *conp, long ucs) 
     790                 :            : {
     791                 :            :         int h;
     792                 :            :         u16 **p1, *p2;
     793                 :            :         struct uni_pagedir *p;
     794                 :            :   
     795                 :            :         /* Only 16-bit codes supported at this time */
     796         [ #  # ]:          0 :         if (ucs > 0xffff)
     797                 :            :                 return -4;              /* Not found */
     798         [ #  # ]:          0 :         else if (ucs < 0x20)
     799                 :            :                 return -1;              /* Not a printable character */
     800         [ #  # ]:          0 :         else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
     801                 :            :                 return -2;                      /* Zero-width space */
     802                 :            :         /*
     803                 :            :          * UNI_DIRECT_BASE indicates the start of the region in the User Zone
     804                 :            :          * which always has a 1:1 mapping to the currently loaded font.  The
     805                 :            :          * UNI_DIRECT_MASK indicates the bit span of the region.
     806                 :            :          */
     807         [ #  # ]:          0 :         else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
     808                 :          0 :                 return ucs & UNI_DIRECT_MASK;
     809                 :            :   
     810         [ #  # ]:          0 :         if (!*conp->vc_uni_pagedir_loc)
     811                 :            :                 return -3;
     812                 :            : 
     813                 :          0 :         p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;  
     814 [ #  # ][ #  # ]:          0 :         if ((p1 = p->uni_pgdir[ucs >> 11]) &&
     815         [ #  # ]:          0 :             (p2 = p1[(ucs >> 6) & 0x1f]) &&
     816                 :          0 :             (h = p2[ucs & 0x3f]) < MAX_GLYPH)
     817                 :          0 :                 return h;
     818                 :            : 
     819                 :            :         return -4;              /* not found */
     820                 :            : }
     821                 :            : 
     822                 :            : /*
     823                 :            :  * This is called at sys_setup time, after memory and the console are
     824                 :            :  * initialized.  It must be possible to call kmalloc(..., GFP_KERNEL)
     825                 :            :  * from this function, hence the call from sys_setup.
     826                 :            :  */
     827                 :            : void __init 
     828                 :          0 : console_map_init(void)
     829                 :            : {
     830                 :            :         int i;
     831                 :            :         
     832         [ #  # ]:          0 :         for (i = 0; i < MAX_NR_CONSOLES; i++)
     833 [ #  # ][ #  # ]:          0 :                 if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
     834                 :          0 :                         con_set_default_unimap(vc_cons[i].d);
     835                 :          0 : }
     836                 :            : 

Generated by: LCOV version 1.9