LCOV - code coverage report
Current view: top level - drivers/tty/vt - consolemap.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_qemu_modules_combined.info Lines: 126 286 44.1 %
Date: 2020-09-30 20:25:01 Functions: 12 23 52.2 %
Branches: 82 240 34.2 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * consolemap.c
       4                 :            :  *
       5                 :            :  * Mapping from internal code (such as Latin-1 or Unicode or IBM PC code)
       6                 :            :  * to font positions.
       7                 :            :  *
       8                 :            :  * aeb, 950210
       9                 :            :  *
      10                 :            :  * Support for multiple unimaps by Jakub Jelinek <jj@ultra.linux.cz>, July 1998
      11                 :            :  *
      12                 :            :  * Fix bug in inverse translation. Stanislav Voronyi <stas@cnti.uanet.kharkov.ua>, Dec 1998
      13                 :            :  *
      14                 :            :  * In order to prevent the following circular lock dependency:
      15                 :            :  *   &mm->mmap_sem --> cpu_hotplug.lock --> console_lock --> &mm->mmap_sem
      16                 :            :  *
      17                 :            :  * We cannot allow page fault to happen while holding the console_lock.
      18                 :            :  * Therefore, all the userspace copy operations have to be done outside
      19                 :            :  * the console_lock critical sections.
      20                 :            :  *
      21                 :            :  * As all the affected functions are all called directly from vt_ioctl(), we
      22                 :            :  * can allocate some small buffers directly on stack without worrying about
      23                 :            :  * stack overflow.
      24                 :            :  */
      25                 :            : 
      26                 :            : #include <linux/module.h>
      27                 :            : #include <linux/kd.h>
      28                 :            : #include <linux/errno.h>
      29                 :            : #include <linux/mm.h>
      30                 :            : #include <linux/slab.h>
      31                 :            : #include <linux/init.h>
      32                 :            : #include <linux/tty.h>
      33                 :            : #include <linux/uaccess.h>
      34                 :            : #include <linux/console.h>
      35                 :            : #include <linux/consolemap.h>
      36                 :            : #include <linux/vt_kern.h>
      37                 :            : #include <linux/string.h>
      38                 :            : 
      39                 :            : static unsigned short translations[][256] = {
      40                 :            :   /* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
      41                 :            :   {
      42                 :            :     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
      43                 :            :     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
      44                 :            :     0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
      45                 :            :     0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
      46                 :            :     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
      47                 :            :     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
      48                 :            :     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
      49                 :            :     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
      50                 :            :     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
      51                 :            :     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
      52                 :            :     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
      53                 :            :     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
      54                 :            :     0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
      55                 :            :     0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
      56                 :            :     0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
      57                 :            :     0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
      58                 :            :     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
      59                 :            :     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
      60                 :            :     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
      61                 :            :     0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
      62                 :            :     0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
      63                 :            :     0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
      64                 :            :     0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
      65                 :            :     0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
      66                 :            :     0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
      67                 :            :     0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
      68                 :            :     0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
      69                 :            :     0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
      70                 :            :     0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
      71                 :            :     0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
      72                 :            :     0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
      73                 :            :     0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
      74                 :            :   }, 
      75                 :            :   /* VT100 graphics mapped to Unicode */
      76                 :            :   {
      77                 :            :     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
      78                 :            :     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
      79                 :            :     0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
      80                 :            :     0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
      81                 :            :     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
      82                 :            :     0x0028, 0x0029, 0x002a, 0x2192, 0x2190, 0x2191, 0x2193, 0x002f,
      83                 :            :     0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
      84                 :            :     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
      85                 :            :     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
      86                 :            :     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
      87                 :            :     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
      88                 :            :     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
      89                 :            :     0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
      90                 :            :     0x2591, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
      91                 :            :     0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
      92                 :            :     0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
      93                 :            :     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
      94                 :            :     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
      95                 :            :     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
      96                 :            :     0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
      97                 :            :     0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
      98                 :            :     0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
      99                 :            :     0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
     100                 :            :     0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
     101                 :            :     0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
     102                 :            :     0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
     103                 :            :     0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
     104                 :            :     0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
     105                 :            :     0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
     106                 :            :     0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
     107                 :            :     0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
     108                 :            :     0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
     109                 :            :   },
     110                 :            :   /* IBM Codepage 437 mapped to Unicode */
     111                 :            :   {
     112                 :            :     0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, 
     113                 :            :     0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
     114                 :            :     0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
     115                 :            :     0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
     116                 :            :     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
     117                 :            :     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
     118                 :            :     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
     119                 :            :     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
     120                 :            :     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
     121                 :            :     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
     122                 :            :     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
     123                 :            :     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
     124                 :            :     0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
     125                 :            :     0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
     126                 :            :     0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
     127                 :            :     0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
     128                 :            :     0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
     129                 :            :     0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
     130                 :            :     0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
     131                 :            :     0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
     132                 :            :     0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
     133                 :            :     0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
     134                 :            :     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
     135                 :            :     0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
     136                 :            :     0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
     137                 :            :     0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
     138                 :            :     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
     139                 :            :     0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
     140                 :            :     0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
     141                 :            :     0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
     142                 :            :     0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
     143                 :            :     0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
     144                 :            :   }, 
     145                 :            :   /* User mapping -- default to codes for direct font mapping */
     146                 :            :   {
     147                 :            :     0xf000, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007,
     148                 :            :     0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f,
     149                 :            :     0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
     150                 :            :     0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
     151                 :            :     0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
     152                 :            :     0xf028, 0xf029, 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f,
     153                 :            :     0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
     154                 :            :     0xf038, 0xf039, 0xf03a, 0xf03b, 0xf03c, 0xf03d, 0xf03e, 0xf03f,
     155                 :            :     0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
     156                 :            :     0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f,
     157                 :            :     0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, 0xf056, 0xf057,
     158                 :            :     0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
     159                 :            :     0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067,
     160                 :            :     0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, 0xf06d, 0xf06e, 0xf06f,
     161                 :            :     0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
     162                 :            :     0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f,
     163                 :            :     0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
     164                 :            :     0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
     165                 :            :     0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
     166                 :            :     0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
     167                 :            :     0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6, 0xf0a7,
     168                 :            :     0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae, 0xf0af,
     169                 :            :     0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xf0b6, 0xf0b7,
     170                 :            :     0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be, 0xf0bf,
     171                 :            :     0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6, 0xf0c7,
     172                 :            :     0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb, 0xf0cc, 0xf0cd, 0xf0ce, 0xf0cf,
     173                 :            :     0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d7,
     174                 :            :     0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc, 0xf0dd, 0xf0de, 0xf0df,
     175                 :            :     0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
     176                 :            :     0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
     177                 :            :     0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
     178                 :            :     0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
     179                 :            :   }
     180                 :            : };
     181                 :            : 
     182                 :            : /* The standard kernel character-to-font mappings are not invertible
     183                 :            :    -- this is just a best effort. */
     184                 :            : 
     185                 :            : #define MAX_GLYPH 512           /* Max possible glyph value */
     186                 :            : 
     187                 :            : static int inv_translate[MAX_NR_CONSOLES];
     188                 :            : 
     189                 :            : struct uni_pagedir {
     190                 :            :         u16             **uni_pgdir[32];
     191                 :            :         unsigned long   refcount;
     192                 :            :         unsigned long   sum;
     193                 :            :         unsigned char   *inverse_translations[4];
     194                 :            :         u16             *inverse_trans_unicode;
     195                 :            : };
     196                 :            : 
     197                 :            : static struct uni_pagedir *dflt;
     198                 :            : 
     199                 :       3232 : static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int i)
     200                 :            : {
     201                 :            :         int j, glyph;
     202                 :       3232 :         unsigned short *t = translations[i];
     203                 :            :         unsigned char *q;
     204                 :            :         
     205         [ +  - ]:       3232 :         if (!p) return;
     206                 :       3232 :         q = p->inverse_translations[i];
     207                 :            : 
     208         [ +  - ]:       3232 :         if (!q) {
     209                 :       3232 :                 q = p->inverse_translations[i] = kmalloc(MAX_GLYPH, GFP_KERNEL);
     210         [ +  - ]:       3232 :                 if (!q) return;
     211                 :            :         }
     212                 :       3232 :         memset(q, 0, MAX_GLYPH);
     213                 :            : 
     214         [ +  + ]:     830624 :         for (j = 0; j < E_TABSZ; j++) {
     215                 :     827392 :                 glyph = conv_uni_to_pc(conp, t[j]);
     216   [ +  +  +  + ]:     827392 :                 if (glyph >= 0 && glyph < MAX_GLYPH && q[glyph] < 32) {
     217                 :            :                         /* prefer '-' above SHY etc. */
     218                 :     656096 :                         q[glyph] = j;
     219                 :            :                 }
     220                 :            :         }
     221                 :            : }
     222                 :            : 
     223                 :        808 : static void set_inverse_trans_unicode(struct vc_data *conp,
     224                 :            :                                       struct uni_pagedir *p)
     225                 :            : {
     226                 :            :         int i, j, k, glyph;
     227                 :            :         u16 **p1, *p2;
     228                 :            :         u16 *q;
     229                 :            : 
     230         [ +  - ]:        808 :         if (!p) return;
     231                 :        808 :         q = p->inverse_trans_unicode;
     232         [ +  - ]:        808 :         if (!q) {
     233                 :        808 :                 q = p->inverse_trans_unicode =
     234                 :        808 :                         kmalloc_array(MAX_GLYPH, sizeof(u16), GFP_KERNEL);
     235         [ +  - ]:        808 :                 if (!q)
     236                 :            :                         return;
     237                 :            :         }
     238                 :        808 :         memset(q, 0, MAX_GLYPH * sizeof(u16));
     239                 :            : 
     240         [ +  + ]:      26664 :         for (i = 0; i < 32; i++) {
     241                 :      25856 :                 p1 = p->uni_pgdir[i];
     242         [ +  + ]:      25856 :                 if (!p1)
     243                 :      23432 :                         continue;
     244         [ +  + ]:      77568 :                 for (j = 0; j < 32; j++) {
     245                 :      77568 :                         p2 = p1[j];
     246         [ +  + ]:      77568 :                         if (!p2)
     247                 :      58176 :                                 continue;
     248         [ +  + ]:    1241088 :                         for (k = 0; k < 64; k++) {
     249                 :    1241088 :                                 glyph = p2[k];
     250         [ +  + ]:    1241088 :                                 if (glyph >= 0 && glyph < MAX_GLYPH
     251         [ +  + ]:     244824 :                                                && q[glyph] < 32)
     252                 :     206848 :                                         q[glyph] = (i << 11) + (j << 6) + k;
     253                 :            :                         }
     254                 :            :                 }
     255                 :            :         }
     256                 :            : }
     257                 :            : 
     258                 :       2828 : unsigned short *set_translate(int m, struct vc_data *vc)
     259                 :            : {
     260                 :       2828 :         inv_translate[vc->vc_num] = m;
     261                 :       2828 :         return translations[m];
     262                 :            : }
     263                 :            : 
     264                 :            : /*
     265                 :            :  * Inverse translation is impossible for several reasons:
     266                 :            :  * 1. The font<->character maps are not 1-1.
     267                 :            :  * 2. The text may have been written while a different translation map
     268                 :            :  *    was active.
     269                 :            :  * Still, it is now possible to a certain extent to cut and paste non-ASCII.
     270                 :            :  */
     271                 :          0 : u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
     272                 :            : {
     273                 :            :         struct uni_pagedir *p;
     274                 :            :         int m;
     275         [ #  # ]:          0 :         if (glyph < 0 || glyph >= MAX_GLYPH)
     276                 :            :                 return 0;
     277                 :            :         else {
     278                 :          0 :                 p = *conp->vc_uni_pagedir_loc;
     279         [ #  # ]:          0 :                 if (!p)
     280                 :          0 :                         return glyph;
     281         [ #  # ]:          0 :                 else if (use_unicode) {
     282         [ #  # ]:          0 :                         if (!p->inverse_trans_unicode)
     283                 :          0 :                                 return glyph;
     284                 :            :                         else
     285                 :          0 :                                 return p->inverse_trans_unicode[glyph];
     286                 :            :                         } else {
     287                 :          0 :                         m = inv_translate[conp->vc_num];
     288         [ #  # ]:          0 :                         if (!p->inverse_translations[m])
     289                 :          0 :                                 return glyph;
     290                 :            :                         else
     291                 :          0 :                                 return p->inverse_translations[m][glyph];
     292                 :            :                         }
     293                 :            :         }
     294                 :            : }
     295                 :            : EXPORT_SYMBOL_GPL(inverse_translate);
     296                 :            : 
     297                 :          0 : static void update_user_maps(void)
     298                 :            : {
     299                 :            :         int i;
     300                 :            :         struct uni_pagedir *p, *q = NULL;
     301                 :            :         
     302         [ #  # ]:          0 :         for (i = 0; i < MAX_NR_CONSOLES; i++) {
     303         [ #  # ]:          0 :                 if (!vc_cons_allocated(i))
     304                 :          0 :                         continue;
     305                 :          0 :                 p = *vc_cons[i].d->vc_uni_pagedir_loc;
     306         [ #  # ]:          0 :                 if (p && p != q) {
     307                 :          0 :                         set_inverse_transl(vc_cons[i].d, p, USER_MAP);
     308                 :          0 :                         set_inverse_trans_unicode(vc_cons[i].d, p);
     309                 :            :                         q = p;
     310                 :            :                 }
     311                 :            :         }
     312                 :          0 : }
     313                 :            : 
     314                 :            : /*
     315                 :            :  * Load customizable translation table
     316                 :            :  * arg points to a 256 byte translation table.
     317                 :            :  *
     318                 :            :  * The "old" variants are for translation directly to font (using the
     319                 :            :  * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
     320                 :            :  * Unicodes explicitly.
     321                 :            :  */
     322                 :          0 : int con_set_trans_old(unsigned char __user * arg)
     323                 :            : {
     324                 :            :         int i;
     325                 :            :         unsigned short inbuf[E_TABSZ];
     326                 :            :         unsigned char ubuf[E_TABSZ];
     327                 :            : 
     328         [ #  # ]:          0 :         if (copy_from_user(ubuf, arg, E_TABSZ))
     329                 :            :                 return -EFAULT;
     330                 :            : 
     331         [ #  # ]:          0 :         for (i = 0; i < E_TABSZ ; i++)
     332                 :          0 :                 inbuf[i] = UNI_DIRECT_BASE | ubuf[i];
     333                 :            : 
     334                 :          0 :         console_lock();
     335                 :          0 :         memcpy(translations[USER_MAP], inbuf, sizeof(inbuf));
     336                 :          0 :         update_user_maps();
     337                 :          0 :         console_unlock();
     338                 :          0 :         return 0;
     339                 :            : }
     340                 :            : 
     341                 :          0 : int con_get_trans_old(unsigned char __user * arg)
     342                 :            : {
     343                 :            :         int i, ch;
     344                 :            :         unsigned short *p = translations[USER_MAP];
     345                 :            :         unsigned char outbuf[E_TABSZ];
     346                 :            : 
     347                 :          0 :         console_lock();
     348         [ #  # ]:          0 :         for (i = 0; i < E_TABSZ ; i++)
     349                 :            :         {
     350                 :          0 :                 ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
     351         [ #  # ]:          0 :                 outbuf[i] = (ch & ~0xff) ? 0 : ch;
     352                 :            :         }
     353                 :          0 :         console_unlock();
     354                 :            : 
     355         [ #  # ]:          0 :         return copy_to_user(arg, outbuf, sizeof(outbuf)) ? -EFAULT : 0;
     356                 :            : }
     357                 :            : 
     358                 :          0 : int con_set_trans_new(ushort __user * arg)
     359                 :            : {
     360                 :            :         unsigned short inbuf[E_TABSZ];
     361                 :            : 
     362         [ #  # ]:          0 :         if (copy_from_user(inbuf, arg, sizeof(inbuf)))
     363                 :            :                 return -EFAULT;
     364                 :            : 
     365                 :          0 :         console_lock();
     366                 :          0 :         memcpy(translations[USER_MAP], inbuf, sizeof(inbuf));
     367                 :          0 :         update_user_maps();
     368                 :          0 :         console_unlock();
     369                 :          0 :         return 0;
     370                 :            : }
     371                 :            : 
     372                 :          0 : int con_get_trans_new(ushort __user * arg)
     373                 :            : {
     374                 :            :         unsigned short outbuf[E_TABSZ];
     375                 :            : 
     376                 :          0 :         console_lock();
     377                 :          0 :         memcpy(outbuf, translations[USER_MAP], sizeof(outbuf));
     378                 :          0 :         console_unlock();
     379                 :            : 
     380         [ #  # ]:          0 :         return copy_to_user(arg, outbuf, sizeof(outbuf)) ? -EFAULT : 0;
     381                 :            : }
     382                 :            : 
     383                 :            : /*
     384                 :            :  * Unicode -> current font conversion 
     385                 :            :  *
     386                 :            :  * A font has at most 512 chars, usually 256.
     387                 :            :  * But one font position may represent several Unicode chars.
     388                 :            :  * A hashtable is somewhat of a pain to deal with, so use a
     389                 :            :  * "paged table" instead.  Simulation has shown the memory cost of
     390                 :            :  * this 3-level paged table scheme to be comparable to a hash table.
     391                 :            :  */
     392                 :            : 
     393                 :            : extern u8 dfont_unicount[];     /* Defined in console_defmap.c */
     394                 :            : extern u16 dfont_unitable[];
     395                 :            : 
     396                 :        404 : static void con_release_unimap(struct uni_pagedir *p)
     397                 :            : {
     398                 :            :         u16 **p1;
     399                 :            :         int i, j;
     400                 :            : 
     401         [ +  - ]:        404 :         if (p == dflt) dflt = NULL;  
     402         [ +  + ]:      12928 :         for (i = 0; i < 32; i++) {
     403                 :      12928 :                 p1 = p->uni_pgdir[i];
     404         [ +  + ]:      12928 :                 if (p1 != NULL) {
     405         [ +  + ]:      38784 :                         for (j = 0; j < 32; j++)
     406                 :      38784 :                                 kfree(p1[j]);
     407                 :       1212 :                         kfree(p1);
     408                 :            :                 }
     409                 :      12928 :                 p->uni_pgdir[i] = NULL;
     410                 :            :         }
     411         [ +  + ]:       1616 :         for (i = 0; i < 4; i++) {
     412                 :       1616 :                 kfree(p->inverse_translations[i]);
     413                 :       1616 :                 p->inverse_translations[i] = NULL;
     414                 :            :         }
     415                 :        404 :         kfree(p->inverse_trans_unicode);
     416                 :        404 :         p->inverse_trans_unicode = NULL;
     417                 :        404 : }
     418                 :            : 
     419                 :            : /* Caller must hold the console lock */
     420                 :       2828 : void con_free_unimap(struct vc_data *vc)
     421                 :            : {
     422                 :            :         struct uni_pagedir *p;
     423                 :            : 
     424                 :       2828 :         p = *vc->vc_uni_pagedir_loc;
     425         [ +  + ]:       2828 :         if (!p)
     426                 :            :                 return;
     427                 :        404 :         *vc->vc_uni_pagedir_loc = NULL;
     428         [ +  - ]:        404 :         if (--p->refcount)
     429                 :            :                 return;
     430                 :        404 :         con_release_unimap(p);
     431                 :        404 :         kfree(p);
     432                 :            : }
     433                 :            :   
     434                 :        808 : 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         [ +  + ]:      51712 :         for (i = 0; i < MAX_NR_CONSOLES; i++) {
     440         [ +  + ]:      50904 :                 if (!vc_cons_allocated(i))
     441                 :      50096 :                         continue;
     442                 :        808 :                 q = *vc_cons[i].d->vc_uni_pagedir_loc;
     443   [ -  +  #  # ]:        808 :                 if (!q || q == p || q->sum != p->sum)
     444                 :        808 :                         continue;
     445         [ #  # ]:          0 :                 for (j = 0; j < 32; j++) {
     446                 :            :                         u16 **p1, **q1;
     447                 :          0 :                         p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
     448         [ #  # ]:          0 :                         if (!p1 && !q1)
     449                 :          0 :                                 continue;
     450         [ #  # ]:          0 :                         if (!p1 || !q1)
     451                 :            :                                 break;
     452         [ #  # ]:          0 :                         for (k = 0; k < 32; k++) {
     453   [ #  #  #  # ]:          0 :                                 if (!p1[k] && !q1[k])
     454                 :          0 :                                         continue;
     455   [ #  #  #  # ]:          0 :                                 if (!p1[k] || !q1[k])
     456                 :            :                                         break;
     457         [ #  # ]:          0 :                                 if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
     458                 :            :                                         break;
     459                 :            :                         }
     460         [ #  # ]:          0 :                         if (k < 32)
     461                 :            :                                 break;
     462                 :            :                 }
     463         [ #  # ]:          0 :                 if (j == 32) {
     464                 :          0 :                         q->refcount++;
     465                 :          0 :                         *conp->vc_uni_pagedir_loc = q;
     466                 :          0 :                         con_release_unimap(p);
     467                 :          0 :                         kfree(p);
     468                 :          0 :                         return 1;
     469                 :            :                 }
     470                 :            :         }
     471                 :            :         return 0;
     472                 :            : }
     473                 :            : 
     474                 :            : static int
     475                 :     244824 : con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
     476                 :            : {
     477                 :            :         int i, n;
     478                 :            :         u16 **p1, *p2;
     479                 :            : 
     480                 :     244824 :         p1 = p->uni_pgdir[n = unicode >> 11];
     481         [ +  + ]:     244824 :         if (!p1) {
     482                 :       2424 :                 p1 = p->uni_pgdir[n] = kmalloc_array(32, sizeof(u16 *),
     483                 :            :                                                      GFP_KERNEL);
     484         [ +  - ]:       2424 :                 if (!p1) return -ENOMEM;
     485         [ +  + ]:      77568 :                 for (i = 0; i < 32; i++)
     486                 :      77568 :                         p1[i] = NULL;
     487                 :            :         }
     488                 :            : 
     489                 :     244824 :         p2 = p1[n = (unicode >> 6) & 0x1f];
     490         [ +  + ]:     244824 :         if (!p2) {
     491                 :      19392 :                 p2 = p1[n] = kmalloc_array(64, sizeof(u16), GFP_KERNEL);
     492         [ +  - ]:      19392 :                 if (!p2) return -ENOMEM;
     493                 :      19392 :                 memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
     494                 :            :         }
     495                 :            : 
     496                 :     244824 :         p2[unicode & 0x3f] = fontpos;
     497                 :            :         
     498                 :     244824 :         p->sum += (fontpos << 20) + unicode;
     499                 :            : 
     500                 :     244824 :         return 0;
     501                 :            : }
     502                 :            : 
     503                 :            : /* Caller must hold the lock */
     504                 :        808 : static int con_do_clear_unimap(struct vc_data *vc)
     505                 :            : {
     506                 :            :         struct uni_pagedir *p, *q;
     507                 :            : 
     508                 :        808 :         p = *vc->vc_uni_pagedir_loc;
     509   [ -  +  #  # ]:        808 :         if (!p || --p->refcount) {
     510                 :        808 :                 q = kzalloc(sizeof(*p), GFP_KERNEL);
     511         [ -  + ]:        808 :                 if (!q) {
     512         [ #  # ]:          0 :                         if (p)
     513                 :          0 :                                 p->refcount++;
     514                 :            :                         return -ENOMEM;
     515                 :            :                 }
     516                 :        808 :                 q->refcount=1;
     517                 :        808 :                 *vc->vc_uni_pagedir_loc = q;
     518                 :            :         } else {
     519         [ #  # ]:          0 :                 if (p == dflt) dflt = NULL;
     520                 :          0 :                 p->refcount++;
     521                 :          0 :                 p->sum = 0;
     522                 :          0 :                 con_release_unimap(p);
     523                 :            :         }
     524                 :            :         return 0;
     525                 :            : }
     526                 :            : 
     527                 :          0 : int con_clear_unimap(struct vc_data *vc)
     528                 :            : {
     529                 :            :         int ret;
     530                 :          0 :         console_lock();
     531                 :          0 :         ret = con_do_clear_unimap(vc);
     532                 :          0 :         console_unlock();
     533                 :          0 :         return ret;
     534                 :            : }
     535                 :            :         
     536                 :          0 : int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
     537                 :            : {
     538                 :            :         int err = 0, err1, i;
     539                 :            :         struct uni_pagedir *p, *q;
     540                 :            :         struct unipair *unilist, *plist;
     541                 :            : 
     542         [ #  # ]:          0 :         if (!ct)
     543                 :            :                 return 0;
     544                 :            : 
     545                 :          0 :         unilist = vmemdup_user(list, ct * sizeof(struct unipair));
     546         [ #  # ]:          0 :         if (IS_ERR(unilist))
     547                 :          0 :                 return PTR_ERR(unilist);
     548                 :            : 
     549                 :          0 :         console_lock();
     550                 :            : 
     551                 :            :         /* Save original vc_unipagdir_loc in case we allocate a new one */
     552                 :          0 :         p = *vc->vc_uni_pagedir_loc;
     553                 :            : 
     554         [ #  # ]:          0 :         if (!p) {
     555                 :            :                 err = -EINVAL;
     556                 :            : 
     557                 :            :                 goto out_unlock;
     558                 :            :         }
     559                 :            :         
     560         [ #  # ]:          0 :         if (p->refcount > 1) {
     561                 :            :                 int j, k;
     562                 :            :                 u16 **p1, *p2, l;
     563                 :            :                 
     564                 :          0 :                 err1 = con_do_clear_unimap(vc);
     565         [ #  # ]:          0 :                 if (err1) {
     566                 :            :                         err = err1;
     567                 :            :                         goto out_unlock;
     568                 :            :                 }
     569                 :            :                 
     570                 :            :                 /*
     571                 :            :                  * Since refcount was > 1, con_clear_unimap() allocated a
     572                 :            :                  * a new uni_pagedir for this vc.  Re: p != q
     573                 :            :                  */
     574                 :          0 :                 q = *vc->vc_uni_pagedir_loc;
     575                 :            : 
     576                 :            :                 /*
     577                 :            :                  * uni_pgdir is a 32*32*64 table with rows allocated
     578                 :            :                  * when its first entry is added.  The unicode value must
     579                 :            :                  * still be incremented for empty rows.  We are copying
     580                 :            :                  * entries from "p" (old) to "q" (new).
     581                 :            :                  */
     582                 :            :                 l = 0;          /* unicode value */
     583         [ #  # ]:          0 :                 for (i = 0; i < 32; i++) {
     584                 :          0 :                 p1 = p->uni_pgdir[i];
     585         [ #  # ]:          0 :                 if (p1)
     586         [ #  # ]:          0 :                         for (j = 0; j < 32; j++) {
     587                 :          0 :                         p2 = p1[j];
     588         [ #  # ]:          0 :                         if (p2) {
     589         [ #  # ]:          0 :                                 for (k = 0; k < 64; k++, l++)
     590         [ #  # ]:          0 :                                 if (p2[k] != 0xffff) {
     591                 :            :                                         /*
     592                 :            :                                          * Found one, copy entry for unicode
     593                 :            :                                          * l with fontpos value p2[k].
     594                 :            :                                          */
     595                 :          0 :                                         err1 = con_insert_unipair(q, l, p2[k]);
     596         [ #  # ]:          0 :                                         if (err1) {
     597                 :          0 :                                                 p->refcount++;
     598                 :          0 :                                                 *vc->vc_uni_pagedir_loc = p;
     599                 :          0 :                                                 con_release_unimap(q);
     600                 :          0 :                                                 kfree(q);
     601                 :          0 :                                                 err = err1;
     602                 :          0 :                                                 goto out_unlock;
     603                 :            :                                         }
     604                 :            :                                 }
     605                 :            :                         } else {
     606                 :            :                                 /* Account for row of 64 empty entries */
     607                 :          0 :                                 l += 64;
     608                 :            :                         }
     609                 :            :                 }
     610                 :            :                 else
     611                 :            :                         /* Account for empty table */
     612                 :          0 :                         l += 32 * 64;
     613                 :            :                 }
     614                 :            : 
     615                 :            :                 /*
     616                 :            :                  * Finished copying font table, set vc_uni_pagedir to new table
     617                 :            :                  */
     618                 :            :                 p = q;
     619         [ #  # ]:          0 :         } else if (p == dflt) {
     620                 :          0 :                 dflt = NULL;
     621                 :            :         }
     622                 :            : 
     623                 :            :         /*
     624                 :            :          * Insert user specified unicode pairs into new table.
     625                 :            :          */
     626         [ #  # ]:          0 :         for (plist = unilist; ct; ct--, plist++) {
     627                 :          0 :                 err1 = con_insert_unipair(p, plist->unicode, plist->fontpos);
     628         [ #  # ]:          0 :                 if (err1)
     629                 :            :                         err = err1;
     630                 :            :         }
     631                 :            :         
     632                 :            :         /*
     633                 :            :          * Merge with fontmaps of any other virtual consoles.
     634                 :            :          */
     635         [ #  # ]:          0 :         if (con_unify_unimap(vc, p))
     636                 :            :                 goto out_unlock;
     637                 :            : 
     638         [ #  # ]:          0 :         for (i = 0; i <= 3; i++)
     639                 :          0 :                 set_inverse_transl(vc, p, i); /* Update inverse translations */
     640                 :          0 :         set_inverse_trans_unicode(vc, p);
     641                 :            : 
     642                 :            : out_unlock:
     643                 :          0 :         console_unlock();
     644                 :          0 :         kvfree(unilist);
     645                 :          0 :         return err;
     646                 :            : }
     647                 :            : 
     648                 :            : /**
     649                 :            :  *      con_set_default_unimap  -       set default unicode map
     650                 :            :  *      @vc: the console we are updating
     651                 :            :  *
     652                 :            :  *      Loads the unimap for the hardware font, as defined in uni_hash.tbl.
     653                 :            :  *      The representation used was the most compact I could come up
     654                 :            :  *      with.  This routine is executed at video setup, and when the
     655                 :            :  *      PIO_FONTRESET ioctl is called. 
     656                 :            :  *
     657                 :            :  *      The caller must hold the console lock
     658                 :            :  */
     659                 :        808 : int con_set_default_unimap(struct vc_data *vc)
     660                 :            : {
     661                 :            :         int i, j, err = 0, err1;
     662                 :            :         u16 *q;
     663                 :            :         struct uni_pagedir *p;
     664                 :            : 
     665         [ -  + ]:        808 :         if (dflt) {
     666                 :          0 :                 p = *vc->vc_uni_pagedir_loc;
     667         [ #  # ]:          0 :                 if (p == dflt)
     668                 :            :                         return 0;
     669                 :            : 
     670                 :          0 :                 dflt->refcount++;
     671                 :          0 :                 *vc->vc_uni_pagedir_loc = dflt;
     672   [ #  #  #  # ]:          0 :                 if (p && !--p->refcount) {
     673                 :          0 :                         con_release_unimap(p);
     674                 :          0 :                         kfree(p);
     675                 :            :                 }
     676                 :            :                 return 0;
     677                 :            :         }
     678                 :            :         
     679                 :            :         /* The default font is always 256 characters */
     680                 :            : 
     681                 :        808 :         err = con_do_clear_unimap(vc);
     682         [ +  - ]:        808 :         if (err)
     683                 :            :                 return err;
     684                 :            :     
     685                 :        808 :         p = *vc->vc_uni_pagedir_loc;
     686                 :            :         q = dfont_unitable;
     687                 :            :         
     688         [ +  + ]:     207656 :         for (i = 0; i < 256; i++)
     689         [ +  + ]:     451672 :                 for (j = dfont_unicount[i]; j; j--) {
     690                 :     244824 :                         err1 = con_insert_unipair(p, *(q++), i);
     691         [ -  + ]:     244824 :                         if (err1)
     692                 :            :                                 err = err1;
     693                 :            :                 }
     694                 :            :                         
     695         [ +  - ]:        808 :         if (con_unify_unimap(vc, p)) {
     696                 :          0 :                 dflt = *vc->vc_uni_pagedir_loc;
     697                 :          0 :                 return err;
     698                 :            :         }
     699                 :            : 
     700         [ +  + ]:       3232 :         for (i = 0; i <= 3; i++)
     701                 :       3232 :                 set_inverse_transl(vc, p, i);   /* Update all inverse translations */
     702                 :        808 :         set_inverse_trans_unicode(vc, p);
     703                 :        808 :         dflt = p;
     704                 :        808 :         return err;
     705                 :            : }
     706                 :            : EXPORT_SYMBOL(con_set_default_unimap);
     707                 :            : 
     708                 :            : /**
     709                 :            :  *      con_copy_unimap         -       copy unimap between two vts
     710                 :            :  *      @dst_vc: target
     711                 :            :  *      @src_vt: source
     712                 :            :  *
     713                 :            :  *      The caller must hold the console lock when invoking this method
     714                 :            :  */
     715                 :       2424 : int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
     716                 :            : {
     717                 :            :         struct uni_pagedir *q;
     718                 :            : 
     719         [ +  - ]:       2424 :         if (!*src_vc->vc_uni_pagedir_loc)
     720                 :            :                 return -EINVAL;
     721         [ +  - ]:       2424 :         if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
     722                 :            :                 return 0;
     723                 :       2424 :         con_free_unimap(dst_vc);
     724                 :       2424 :         q = *src_vc->vc_uni_pagedir_loc;
     725                 :       2424 :         q->refcount++;
     726                 :       2424 :         *dst_vc->vc_uni_pagedir_loc = q;
     727                 :       2424 :         return 0;
     728                 :            : }
     729                 :            : EXPORT_SYMBOL(con_copy_unimap);
     730                 :            : 
     731                 :            : /**
     732                 :            :  *      con_get_unimap          -       get the unicode map
     733                 :            :  *      @vc: the console to read from
     734                 :            :  *
     735                 :            :  *      Read the console unicode data for this console. Called from the ioctl
     736                 :            :  *      handlers.
     737                 :            :  */
     738                 :          0 : int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
     739                 :            : {
     740                 :            :         int i, j, k, ret = 0;
     741                 :            :         ushort ect;
     742                 :            :         u16 **p1, *p2;
     743                 :            :         struct uni_pagedir *p;
     744                 :            :         struct unipair *unilist;
     745                 :            : 
     746                 :          0 :         unilist = kvmalloc_array(ct, sizeof(struct unipair), GFP_KERNEL);
     747         [ #  # ]:          0 :         if (!unilist)
     748                 :            :                 return -ENOMEM;
     749                 :            : 
     750                 :          0 :         console_lock();
     751                 :            : 
     752                 :            :         ect = 0;
     753         [ #  # ]:          0 :         if (*vc->vc_uni_pagedir_loc) {
     754                 :            :                 p = *vc->vc_uni_pagedir_loc;
     755         [ #  # ]:          0 :                 for (i = 0; i < 32; i++) {
     756                 :          0 :                 p1 = p->uni_pgdir[i];
     757         [ #  # ]:          0 :                 if (p1)
     758         [ #  # ]:          0 :                         for (j = 0; j < 32; j++) {
     759                 :          0 :                         p2 = *(p1++);
     760         [ #  # ]:          0 :                         if (p2)
     761         [ #  # ]:          0 :                                 for (k = 0; k < 64; k++, p2++) {
     762         [ #  # ]:          0 :                                         if (*p2 >= MAX_GLYPH)
     763                 :          0 :                                                 continue;
     764         [ #  # ]:          0 :                                         if (ect < ct) {
     765                 :          0 :                                                 unilist[ect].unicode =
     766                 :            :                                                         (i<<11)+(j<<6)+k;
     767                 :          0 :                                                 unilist[ect].fontpos = *p2;
     768                 :            :                                         }
     769                 :          0 :                                         ect++;
     770                 :            :                                 }
     771                 :            :                         }
     772                 :            :                 }
     773                 :            :         }
     774                 :          0 :         console_unlock();
     775         [ #  # ]:          0 :         if (copy_to_user(list, unilist, min(ect, ct) * sizeof(struct unipair)))
     776                 :            :                 ret = -EFAULT;
     777                 :          0 :         put_user(ect, uct);
     778                 :          0 :         kvfree(unilist);
     779   [ #  #  #  # ]:          0 :         return ret ? ret : (ect <= ct) ? 0 : -ENOMEM;
     780                 :            : }
     781                 :            : 
     782                 :            : /*
     783                 :            :  * Always use USER_MAP. These functions are used by the keyboard,
     784                 :            :  * which shouldn't be affected by G0/G1 switching, etc.
     785                 :            :  * If the user map still contains default values, i.e. the
     786                 :            :  * direct-to-font mapping, then assume user is using Latin1.
     787                 :            :  *
     788                 :            :  * FIXME: at some point we need to decide if we want to lock the table
     789                 :            :  * update element itself via the keyboard_event_lock for consistency with the
     790                 :            :  * keyboard driver as well as the consoles
     791                 :            :  */
     792                 :            : /* may be called during an interrupt */
     793                 :          0 : u32 conv_8bit_to_uni(unsigned char c)
     794                 :            : {
     795                 :          0 :         unsigned short uni = translations[USER_MAP][c];
     796         [ #  # ]:          0 :         return uni == (0xf000 | c) ? c : uni;
     797                 :            : }
     798                 :            : 
     799                 :          0 : int conv_uni_to_8bit(u32 uni)
     800                 :            : {
     801                 :            :         int c;
     802         [ #  # ]:          0 :         for (c = 0; c < 0x100; c++)
     803   [ #  #  #  # ]:          0 :                 if (translations[USER_MAP][c] == uni ||
     804         [ #  # ]:          0 :                    (translations[USER_MAP][c] == (c | 0xf000) && uni == c))
     805                 :          0 :                         return c;
     806                 :            :         return -1;
     807                 :            : }
     808                 :            : 
     809                 :            : int
     810                 :    1026642 : conv_uni_to_pc(struct vc_data *conp, long ucs) 
     811                 :            : {
     812                 :            :         int h;
     813                 :            :         u16 **p1, *p2;
     814                 :            :         struct uni_pagedir *p;
     815                 :            :   
     816                 :            :         /* Only 16-bit codes supported at this time */
     817         [ +  - ]:    1026642 :         if (ucs > 0xffff)
     818                 :            :                 return -4;              /* Not found */
     819         [ +  + ]:    1026642 :         else if (ucs < 0x20)
     820                 :            :                 return -1;              /* Not a printable character */
     821         [ +  - ]:     974122 :         else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
     822                 :            :                 return -2;                      /* Zero-width space */
     823                 :            :         /*
     824                 :            :          * UNI_DIRECT_BASE indicates the start of the region in the User Zone
     825                 :            :          * which always has a 1:1 mapping to the currently loaded font.  The
     826                 :            :          * UNI_DIRECT_MASK indicates the bit span of the region.
     827                 :            :          */
     828         [ +  + ]:     974122 :         else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
     829                 :     206848 :                 return ucs & UNI_DIRECT_MASK;
     830                 :            :   
     831         [ +  - ]:     767274 :         if (!*conp->vc_uni_pagedir_loc)
     832                 :            :                 return -3;
     833                 :            : 
     834                 :            :         p = *conp->vc_uni_pagedir_loc;
     835   [ +  -  +  + ]:    1534548 :         if ((p1 = p->uni_pgdir[ucs >> 11]) &&
     836         [ +  + ]:    1530508 :             (p2 = p1[(ucs >> 6) & 0x1f]) &&
     837                 :     763234 :             (h = p2[ucs & 0x3f]) < MAX_GLYPH)
     838                 :     696978 :                 return h;
     839                 :            : 
     840                 :            :         return -4;              /* not found */
     841                 :            : }
     842                 :            : 
     843                 :            : /*
     844                 :            :  * This is called at sys_setup time, after memory and the console are
     845                 :            :  * initialized.  It must be possible to call kmalloc(..., GFP_KERNEL)
     846                 :            :  * from this function, hence the call from sys_setup.
     847                 :            :  */
     848                 :            : void __init 
     849                 :        404 : console_map_init(void)
     850                 :            : {
     851                 :            :         int i;
     852                 :            :         
     853         [ +  + ]:      25856 :         for (i = 0; i < MAX_NR_CONSOLES; i++)
     854   [ +  +  +  - ]:      25452 :                 if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
     855                 :        404 :                         con_set_default_unimap(vc_cons[i].d);
     856                 :        404 : }
     857                 :            : 

Generated by: LCOV version 1.14