Print this page
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    9259 libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Revert "NEX-16819 loader UEFI support"
This reverts commit ec06b9fc617b99234e538bf2e7e4d02a24993e0c.
Reverting due to failures in the zfs-tests and the sharefs-tests
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>


   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 /*
  30  * Generic keyboard support: translation
  31  *
  32  * This module is project private.  Please see PSARC/1998/176 and
  33  * PSARC/1998/026 for references to the kbtrans module.
  34  *
  35  * It is believed that it is safe to call these functions within debugger mode
  36  * except kbtrans_dprintf.  Debugger mode is a single threaded mode where most
  37  * kernel services are not available, including memory allocation.  Debugger
  38  * mode is for kmdb and OBP debugging, where the debugger calls back into the
  39  * kernel to obtain console input.
  40  *
  41  * Please be _very_ careful about what external functions you call.
  42  */
  43 
  44 #define KEYMAP_SIZE_VARIABLE
  45 
  46 #include <sys/types.h>
  47 #include <sys/cred.h>
  48 #include <sys/ddi.h>
  49 #include <sys/sunddi.h>
  50 #include <sys/kmem.h>
  51 #include <sys/kbd.h>
  52 #include <sys/cmn_err.h>
  53 #include <sys/modctl.h>
  54 #include <sys/kbio.h>
  55 #include <sys/vuid_event.h>
  56 #include <sys/consdev.h>
  57 #include <sys/kbtrans.h>
  58 #include <sys/errno.h>
  59 #include <sys/promif.h>
  60 #include <sys/varargs.h>
  61 #include "kbtrans_lower.h"
  62 
  63 /*
  64  * Internal Function Prototypes
  65  */
  66 static boolean_t        kbtrans_do_compose(struct kbtrans_lower *, ushort_t,
  67                             ushort_t, ushort_t *);
  68 static void             kbtrans_translate(struct kbtrans_lower *,
  69                                 struct keyboard_callback *, kbtrans_key_t,
  70                                 enum keystate);
  71 /*
  72  * kbtrans_processkey:
  73  *
  74  *      lower   - state information used by the calling driver
  75  *                this parameter is passed back to the callback routines.
  76  *      key     - scancode
  77  *      state   - KEY_PRESSED / KEY_RELEASED
  78  *
  79  * This routine checks to see if there is a raw callback, and calls it
  80  * if it exists.  If there is no raw callback, the key is translated.
  81  * The raw callback allows the driver that called the translation module
  82  * to be passed untranslated scancodes.
  83  */
  84 void
  85 kbtrans_processkey(struct kbtrans_lower *lower,
  86         struct keyboard_callback        *cb,
  87         kbtrans_key_t                   key,
  88         enum keystate                   state)
  89 {
  90         DPRINTF(PRINT_L0, PRINT_MASK_ALL, (lower, "kbtrans_processkey: "
  91                 "newstate=%d key=%d", state, key));
  92 
  93         /*
  94          * If there is a raw routine, then call it and return.
  95          */
  96         if (cb->kc_keypressed_raw != NULL) {
  97 
  98                 if (state == KEY_PRESSED) {
  99 
 100                         cb->kc_keypressed_raw(lower->kbtrans_upper, key);
 101                 } else {
 102 
 103                         cb->kc_keyreleased_raw(lower->kbtrans_upper, key);
 104                 }
 105 
 106                 return;
 107         }
 108 
 109         /*
 110          * translate the scancode into a key.
 111          */
 112         kbtrans_translate(lower, cb, key, state);
 113 }
 114 
 115 
 116 /*
 117  * kbtrans_translate:
 118  *
 119  *      lower   - state information used by the calling driver
 120  *                this parameter is passed back to the callback routines.
 121  *      key             - scan code
 122  *      state   - KEY_PRESSED / KEY_RELEASED
 123  *
 124  * Called to process key events if we are in TR_ASCII or TR_EVENT
 125  * (sunview) mode.  This routine will call the appropriate translation_callback
 126  * for the character when it is done translating it.
 127  */
 128 static void
 129 kbtrans_translate(struct kbtrans_lower  *lower,
 130         struct keyboard_callback        *cb,
 131         kbtrans_key_t                   key,
 132         enum keystate                   newstate)
 133 {
 134         unsigned                shiftmask;
 135         register ushort_t       entry;
 136         register ushort_t       entrytype;
 137         ushort_t                result_iso;
 138         unsigned short          *ke;
 139         int                     i;
 140         boolean_t               good_compose;
 141 
 142         DPRINTF(PRINT_L0, PRINT_MASK_ALL, (lower, "KEY TRANSLATE "
 143                 "newstate=0x%x key=0x%x\n", newstate, key));
 144 
 145         if (lower->kbtrans_keyboard == NULL) {
 146                 /*
 147                  * Nobody has told us about this keyboard yet.
 148                  */
 149                 return;
 150         }
 151 
 152         /*
 153          * Get the current state of the shiftmask
 154          */
 155         shiftmask = lower->kbtrans_shiftmask;
 156 
 157         /*
 158          * If the key has been released, then or in the UPMASK flag.


 171                  * This is a gross error.  Cancel the repeat key and exit,
 172                  * we can not translate this scancode.
 173                  */
 174                 cb->kc_cancel_repeat(lower->kbtrans_upper);
 175 
 176                 return;
 177         }
 178 
 179         /*
 180          * Get the key for this scancode.
 181          */
 182         entry = *ke;
 183 
 184         if (entry == NONL) {
 185                 /*
 186                  * NONL appears only in the Num Lock table, and indicates that
 187                  * this key is not affected by Num Lock.  This means we should
 188                  * ask for the table we would have gotten had Num Lock not been
 189                  * down, and translate using that table.
 190                  */
 191                 ke = kbtrans_find_entry(lower, shiftmask & ~NUMLOCKMASK,
 192                         key);
 193 
 194                 if (ke == NULL) {
 195                         /*
 196                          * This is a gross error.  Cancel the repeat key and
 197                          * exit, we can not translate this scancode.
 198                          */
 199                         cb->kc_cancel_repeat(lower->kbtrans_upper);
 200 
 201                         return;
 202                 }
 203 
 204                 /*
 205                  * Get the new key for this scancode.
 206                  */
 207                 entry = *ke;
 208         }
 209 
 210         /*
 211          * The entrytype indicates what category of key we are processing.
 212          * Categories include shift keys, function keys, and numeric keypad
 213          * keys.
 214          */
 215         entrytype = (ushort_t)(entry & 0xFF00);
 216 
 217         if (entrytype == SHIFTKEYS) {
 218                 /*
 219                  * Handle the state of toggle shifts specially.
 220                  * Ups should be ignored, and downs should be mapped to ups if
 221                  * that shift is currently on.
 222                  */
 223                 if ((1 << (entry & 0x0F)) &
 224                     lower->kbtrans_keyboard->k_toggleshifts) {
 225                         if ((1 << (entry & 0x0F)) &
 226                                 lower->kbtrans_togglemask) {
 227                                 newstate = KEY_RELEASED; /* toggling off */
 228                         } else {
 229                                 newstate = KEY_PRESSED; /* toggling on */
 230                         }
 231                 }
 232         } else {
 233                 /*
 234                  * Handle Compose and floating accent key sequences
 235                  */
 236                 switch (lower->kbtrans_state) {
 237                 case COMPOSE1:
 238                         if (newstate == KEY_RELEASED)
 239 
 240                                 return;
 241 
 242                         if (entry < ASCII_SET_SIZE) {
 243                                 if (lower->kbtrans_compose_map[entry] >= 0) {
 244                                         lower->kbtrans_compose_key = entry;
 245                                         lower->kbtrans_state = COMPOSE2;
 246 
 247                                         return;
 248                                 }
 249                         }
 250                         lower->kbtrans_state = NORMAL;
 251                         lower->kbtrans_led_state &= ~LED_COMPOSE;
 252 
 253                         cb->kc_setled(lower->kbtrans_upper);
 254 
 255                         return;
 256 
 257                 case COMPOSE2:
 258                         if (newstate == KEY_RELEASED)
 259                                 return;
 260 
 261                         /* next state is "normal" */
 262                         lower->kbtrans_state = NORMAL;
 263                         lower->kbtrans_led_state &= ~LED_COMPOSE;
 264 
 265                         cb->kc_setled(lower->kbtrans_upper);
 266 
 267                         good_compose = kbtrans_do_compose(lower,
 268                                 lower->kbtrans_compose_key, entry,
 269                                 &result_iso);
 270                         if (good_compose) {
 271                                 if (lower->kbtrans_compat)
 272                                         result_iso += ISO_FIRST;
 273                                 else
 274                                         result_iso += EUC_FIRST;
 275                                 cb->kc_keypressed(lower->kbtrans_upper,
 276                                     entrytype, key, result_iso);
 277                         }
 278                         return;
 279 
 280                 case FLTACCENT:
 281                         if (newstate == KEY_RELEASED)
 282 
 283                                 return;
 284 
 285                         /* next state is "normal" */
 286                         lower->kbtrans_state = NORMAL;
 287                         for (i = 0;
 288                             (lower->kbtrans_fltaccent_table[i].fa_entry
 289                                 != lower->kbtrans_fltaccent_entry) ||
 290                             (lower->kbtrans_fltaccent_table[i].ascii != entry);
 291                             i++) {
 292                                 if (lower->kbtrans_fltaccent_table[i].fa_entry
 293                                     == 0) {
 294                                         /* Invalid second key: ignore key */
 295 
 296                                         return;
 297                                 }
 298                         }
 299 
 300                         cb->kc_keypressed(lower->kbtrans_upper, entrytype,
 301                                         key, (lower->kbtrans_compat ?
 302                                                 ISO_FIRST : EUC_FIRST) +
 303                                         lower->kbtrans_fltaccent_table[i].iso);
 304 
 305                         return;
 306                 }
 307         }
 308 
 309         /*
 310          * If the key is going down, and it's not one of the keys that doesn't
 311          * auto-repeat, set up the auto-repeat timeout.
 312          *
 313          * The keys that don't auto-repeat are the Compose key,
 314          * the shift keys, the "bucky bit" keys, the "floating accent" keys,
 315          * and the function keys when in TR_EVENT mode.
 316          */
 317         if (newstate == KEY_PRESSED && entrytype != SHIFTKEYS &&
 318             entrytype != BUCKYBITS && entrytype != FUNNY &&
 319             entrytype != FA_CLASS) {
 320 
 321                 if (lower->kbtrans_repeatkey != key) {
 322                         cb->kc_cancel_repeat(lower->kbtrans_upper);
 323                         cb->kc_setup_repeat(lower->kbtrans_upper, entrytype,


 325                 }
 326                 /* key going up */
 327         } else if (key == lower->kbtrans_repeatkey) {
 328 
 329                 cb->kc_cancel_repeat(lower->kbtrans_upper);
 330         }
 331 
 332         if (newstate == KEY_RELEASED) {
 333                 cb->kc_keyreleased(lower->kbtrans_upper, key);
 334         }
 335 
 336         /*
 337          * We assume here that keys other than shift keys and bucky keys have
 338          * entries in the "up" table that cause nothing to be done, and thus we
 339          * don't have to check for newstate == KEY_RELEASED.
 340          */
 341         switch (entrytype) {
 342 
 343         case 0x0:               /* regular key */
 344                 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key,
 345                         entry | lower->kbtrans_buckybits);
 346                 break;
 347 
 348         case SHIFTKEYS: {
 349                 uint_t shiftbit = 1 << (entry & 0x0F);
 350 
 351                 /* Modify toggle state (see toggle processing above) */
 352                 if (shiftbit & lower->kbtrans_keyboard->k_toggleshifts) {
 353                         if (newstate == KEY_RELEASED) {
 354                                 if (shiftbit == CAPSMASK) {
 355                                         lower->kbtrans_led_state &=
 356                                                 ~LED_CAPS_LOCK;
 357 
 358                                         cb->kc_setled(lower->kbtrans_upper);
 359 
 360                                 } else if (shiftbit == NUMLOCKMASK) {
 361                                         lower->kbtrans_led_state &=
 362                                                     ~LED_NUM_LOCK;
 363 
 364                                         cb->kc_setled(lower->kbtrans_upper);
 365                                 }


 377                                         cb->kc_setled(lower->kbtrans_upper);
 378                                 }
 379                                 lower->kbtrans_togglemask |= shiftbit;
 380                         }
 381                 }
 382 
 383                 if (newstate == KEY_RELEASED)
 384                         lower->kbtrans_shiftmask &= ~shiftbit;
 385                 else
 386                         lower->kbtrans_shiftmask |= shiftbit;
 387 
 388                 if (newstate == KEY_PRESSED) {
 389                         cb->kc_keypressed(lower->kbtrans_upper, entrytype, key,
 390                                 entry);
 391                 }
 392 
 393                 break;
 394                 }
 395 
 396         case BUCKYBITS:
 397                 lower->kbtrans_buckybits ^= 1 << (7 + (entry & 0x0F));
 398 
 399                 if (newstate == KEY_PRESSED) {
 400                         cb->kc_keypressed(lower->kbtrans_upper, entrytype, key,
 401                                 entry);
 402                 }
 403 
 404                 break;
 405 
 406         case FUNNY:
 407                 switch (entry) {
 408                 case NOP:
 409                         break;
 410 
 411                 case IDLE:
 412                         /* Fall thru into RESET code */
 413                         /* FALLTHRU */
 414                 case RESET:
 415                 case ERROR:
 416                         lower->kbtrans_shiftmask &=
 417                                 lower->kbtrans_keyboard->k_idleshifts;


 463                 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key, entry);
 464 
 465                 break;
 466 
 467         /*
 468          * Remember when adding new entries that,
 469          * if they should NOT auto-repeat,
 470          * they should be put into the IF statement
 471          * just above this switch block.
 472          */
 473         case PADKEYS:
 474                 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key, entry);
 475 
 476                 break;
 477         }
 478 }
 479 
 480 /*
 481  * kbtrans_do_compose:
 482  *      Given a two key compose sequence, lookup the iso equivalent and put
 483  *      the result in the result_iso_ptr.
 484  */
 485 static boolean_t
 486 kbtrans_do_compose(struct kbtrans_lower *lower,
 487                 ushort_t        first_entry,
 488                 ushort_t        second_entry,
 489                 ushort_t        *result_iso_ptr)
 490 {
 491         struct compose_sequence_t *ptr;
 492         ushort_t        tmp;
 493 
 494         /*
 495          * Validate the second keystroke.
 496          */
 497         if (second_entry >= ASCII_SET_SIZE)
 498                 return (B_FALSE);
 499 
 500         if (lower->kbtrans_compose_map[second_entry] < 0)
 501                 return (B_FALSE);
 502 
 503         /*
 504          * Get them in code order, rather than press order.
 505          */
 506         if (first_entry > second_entry) {
 507                 tmp = first_entry;
 508                 first_entry = second_entry;
 509                 second_entry = tmp;
 510         }
 511 
 512         ptr = lower->kbtrans_compose_table +
 513                     lower->kbtrans_compose_map[first_entry];
 514 
 515         while (ptr->first == first_entry) {
 516                 if (ptr->second == second_entry) {
 517                         *result_iso_ptr = ptr->iso;
 518 
 519                         return (B_TRUE);
 520                 }
 521                 ptr++;
 522         }
 523         return (B_FALSE);
 524 }
 525 
 526 
 527 /*
 528  * kbtrans_find_entry:
 529  *      This routine finds the entry corresponding to the current shift
 530  *      state and keycode.
 531  */
 532 unsigned short *
 533 kbtrans_find_entry(struct kbtrans_lower *lower,
 534         register uint_t                 mask,
 535         kbtrans_key_t                   key_station)
 536 {
 537         register struct keyboard *kp;
 538         keymap_entry_t *km;
 539         struct exception_map *ex;
 540 
 541         kp = lower->kbtrans_keyboard;
 542 
 543         if (kp == NULL)
 544                 return (NULL);
 545 
 546         if (key_station < 0 || key_station >= kp->k_keymap_size)
 547                 return (NULL);
 548 
 549         ex = kp->k_except;
 550         if (ex != NULL) {
 551                 for (; ex->exc_care != 0; ex++) {
 552                         if ((mask & ex->exc_care) == ex->exc_mask &&
 553                             key_station == ex->exc_key)
 554                                 return (&ex->exc_entry);




   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 


  27 /*
  28  * Generic keyboard support: translation
  29  *
  30  * This module is project private.  Please see PSARC/1998/176 and
  31  * PSARC/1998/026 for references to the kbtrans module.
  32  *
  33  * It is believed that it is safe to call these functions within debugger mode
  34  * except kbtrans_dprintf.  Debugger mode is a single threaded mode where most
  35  * kernel services are not available, including memory allocation.  Debugger
  36  * mode is for kmdb and OBP debugging, where the debugger calls back into the
  37  * kernel to obtain console input.
  38  *
  39  * Please be _very_ careful about what external functions you call.
  40  */
  41 
  42 #define KEYMAP_SIZE_VARIABLE
  43 
  44 #include <sys/types.h>
  45 #include <sys/cred.h>
  46 #include <sys/ddi.h>
  47 #include <sys/sunddi.h>
  48 #include <sys/kmem.h>
  49 #include <sys/kbd.h>
  50 #include <sys/cmn_err.h>
  51 #include <sys/modctl.h>
  52 #include <sys/kbio.h>
  53 #include <sys/vuid_event.h>
  54 #include <sys/consdev.h>
  55 #include <sys/kbtrans.h>
  56 #include <sys/errno.h>
  57 #include <sys/promif.h>
  58 #include <sys/varargs.h>
  59 #include "kbtrans_lower.h"
  60 
  61 /*
  62  * Internal Function Prototypes
  63  */
  64 static boolean_t kbtrans_do_compose(struct kbtrans_lower *, keymap_entry_t,
  65     keymap_entry_t, keymap_entry_t *);
  66 static void kbtrans_translate(struct kbtrans_lower *,
  67     struct keyboard_callback *, kbtrans_key_t, enum keystate);
  68 
  69 /*
  70  * kbtrans_processkey:
  71  *
  72  *      lower   - state information used by the calling driver
  73  *                this parameter is passed back to the callback routines.
  74  *      key     - scancode
  75  *      state   - KEY_PRESSED / KEY_RELEASED
  76  *
  77  * This routine checks to see if there is a raw callback, and calls it
  78  * if it exists.  If there is no raw callback, the key is translated.
  79  * The raw callback allows the driver that called the translation module
  80  * to be passed untranslated scancodes.
  81  */
  82 void
  83 kbtrans_processkey(struct kbtrans_lower *lower,
  84     struct keyboard_callback *cb, kbtrans_key_t key, enum keystate state)


  85 {
  86         DPRINTF(PRINT_L0, PRINT_MASK_ALL, (lower, "kbtrans_processkey: "
  87             "newstate=%d key=%d", state, key));
  88 
  89         /*
  90          * If there is a raw routine, then call it and return.
  91          */
  92         if (cb->kc_keypressed_raw != NULL) {
  93 
  94                 if (state == KEY_PRESSED) {
  95 
  96                         cb->kc_keypressed_raw(lower->kbtrans_upper, key);
  97                 } else {
  98 
  99                         cb->kc_keyreleased_raw(lower->kbtrans_upper, key);
 100                 }
 101 
 102                 return;
 103         }
 104 
 105         /*
 106          * translate the scancode into a key.
 107          */
 108         kbtrans_translate(lower, cb, key, state);
 109 }
 110 
 111 
 112 /*
 113  * kbtrans_translate:
 114  *
 115  *      lower   - state information used by the calling driver
 116  *                this parameter is passed back to the callback routines.
 117  *      key             - scan code
 118  *      state   - KEY_PRESSED / KEY_RELEASED
 119  *
 120  * Called to process key events if we are in TR_ASCII or TR_EVENT
 121  * (sunview) mode.  This routine will call the appropriate translation_callback
 122  * for the character when it is done translating it.
 123  */
 124 static void
 125 kbtrans_translate(struct kbtrans_lower *lower, struct keyboard_callback *cb,
 126     kbtrans_key_t key, enum keystate newstate)


 127 {
 128         unsigned                shiftmask;
 129         register keymap_entry_t entry;
 130         register unsigned       entrytype;
 131         keymap_entry_t          result;
 132         keymap_entry_t          *ke;
 133         int                     i;
 134         boolean_t               good_compose;
 135 
 136         DPRINTF(PRINT_L0, PRINT_MASK_ALL, (lower, "KEY TRANSLATE "
 137             "newstate=0x%x key=0x%x\n", newstate, key));
 138 
 139         if (lower->kbtrans_keyboard == NULL) {
 140                 /*
 141                  * Nobody has told us about this keyboard yet.
 142                  */
 143                 return;
 144         }
 145 
 146         /*
 147          * Get the current state of the shiftmask
 148          */
 149         shiftmask = lower->kbtrans_shiftmask;
 150 
 151         /*
 152          * If the key has been released, then or in the UPMASK flag.


 165                  * This is a gross error.  Cancel the repeat key and exit,
 166                  * we can not translate this scancode.
 167                  */
 168                 cb->kc_cancel_repeat(lower->kbtrans_upper);
 169 
 170                 return;
 171         }
 172 
 173         /*
 174          * Get the key for this scancode.
 175          */
 176         entry = *ke;
 177 
 178         if (entry == NONL) {
 179                 /*
 180                  * NONL appears only in the Num Lock table, and indicates that
 181                  * this key is not affected by Num Lock.  This means we should
 182                  * ask for the table we would have gotten had Num Lock not been
 183                  * down, and translate using that table.
 184                  */
 185                 ke = kbtrans_find_entry(lower, shiftmask & ~NUMLOCKMASK, key);

 186 
 187                 if (ke == NULL) {
 188                         /*
 189                          * This is a gross error.  Cancel the repeat key and
 190                          * exit, we can not translate this scancode.
 191                          */
 192                         cb->kc_cancel_repeat(lower->kbtrans_upper);
 193 
 194                         return;
 195                 }
 196 
 197                 /*
 198                  * Get the new key for this scancode.
 199                  */
 200                 entry = *ke;
 201         }
 202 
 203         /*
 204          * The entrytype indicates what category of key we are processing.
 205          * Categories include shift keys, function keys, and numeric keypad
 206          * keys.
 207          */
 208         entrytype = KEYFLAGS(entry);
 209 
 210         if (entrytype == SHIFTKEYS) {
 211                 /*
 212                  * Handle the state of toggle shifts specially.
 213                  * Ups should be ignored, and downs should be mapped to ups if
 214                  * that shift is currently on.
 215                  */
 216                 if ((1 << (entry & 0x0F)) &
 217                     lower->kbtrans_keyboard->k_toggleshifts) {
 218                         if ((1 << (entry & 0x0F)) & lower->kbtrans_togglemask) {

 219                                 newstate = KEY_RELEASED; /* toggling off */
 220                         } else {
 221                                 newstate = KEY_PRESSED; /* toggling on */
 222                         }
 223                 }
 224         } else {
 225                 /*
 226                  * Handle Compose and floating accent key sequences
 227                  */
 228                 switch (lower->kbtrans_state) {
 229                 case COMPOSE1:
 230                         if (newstate == KEY_RELEASED)

 231                                 return;
 232 
 233                         if (entry < ASCII_SET_SIZE) {
 234                                 if (lower->kbtrans_compose_map[entry] >= 0) {
 235                                         lower->kbtrans_compose_key = entry;
 236                                         lower->kbtrans_state = COMPOSE2;
 237 
 238                                         return;
 239                                 }
 240                         }
 241                         lower->kbtrans_state = NORMAL;
 242                         lower->kbtrans_led_state &= ~LED_COMPOSE;
 243 
 244                         cb->kc_setled(lower->kbtrans_upper);
 245 
 246                         return;
 247 
 248                 case COMPOSE2:
 249                         if (newstate == KEY_RELEASED)
 250                                 return;
 251 
 252                         /* next state is "normal" */
 253                         lower->kbtrans_state = NORMAL;
 254                         lower->kbtrans_led_state &= ~LED_COMPOSE;
 255 
 256                         cb->kc_setled(lower->kbtrans_upper);
 257 
 258                         good_compose = kbtrans_do_compose(lower,
 259                             lower->kbtrans_compose_key, entry, &result);

 260                         if (good_compose) {




 261                                 cb->kc_keypressed(lower->kbtrans_upper,
 262                                     entrytype, key, result);
 263                         }
 264                         return;
 265 
 266                 case FLTACCENT:
 267                         if (newstate == KEY_RELEASED)

 268                                 return;
 269 
 270                         /* next state is "normal" */
 271                         lower->kbtrans_state = NORMAL;
 272                         for (i = 0;
 273                             (lower->kbtrans_fltaccent_table[i].fa_entry !=
 274                             lower->kbtrans_fltaccent_entry) ||
 275                             (lower->kbtrans_fltaccent_table[i].ascii != entry);
 276                             i++) {
 277                                 if (lower->kbtrans_fltaccent_table[i].fa_entry
 278                                     == 0) {
 279                                         /* Invalid second key: ignore key */
 280 
 281                                         return;
 282                                 }
 283                         }
 284 
 285                         cb->kc_keypressed(lower->kbtrans_upper, entrytype, key,
 286                             lower->kbtrans_fltaccent_table[i].utf8);


 287 
 288                         return;
 289                 }
 290         }
 291 
 292         /*
 293          * If the key is going down, and it's not one of the keys that doesn't
 294          * auto-repeat, set up the auto-repeat timeout.
 295          *
 296          * The keys that don't auto-repeat are the Compose key,
 297          * the shift keys, the "bucky bit" keys, the "floating accent" keys,
 298          * and the function keys when in TR_EVENT mode.
 299          */
 300         if (newstate == KEY_PRESSED && entrytype != SHIFTKEYS &&
 301             entrytype != BUCKYBITS && entrytype != FUNNY &&
 302             entrytype != FA_CLASS) {
 303 
 304                 if (lower->kbtrans_repeatkey != key) {
 305                         cb->kc_cancel_repeat(lower->kbtrans_upper);
 306                         cb->kc_setup_repeat(lower->kbtrans_upper, entrytype,


 308                 }
 309                 /* key going up */
 310         } else if (key == lower->kbtrans_repeatkey) {
 311 
 312                 cb->kc_cancel_repeat(lower->kbtrans_upper);
 313         }
 314 
 315         if (newstate == KEY_RELEASED) {
 316                 cb->kc_keyreleased(lower->kbtrans_upper, key);
 317         }
 318 
 319         /*
 320          * We assume here that keys other than shift keys and bucky keys have
 321          * entries in the "up" table that cause nothing to be done, and thus we
 322          * don't have to check for newstate == KEY_RELEASED.
 323          */
 324         switch (entrytype) {
 325 
 326         case 0x0:               /* regular key */
 327                 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key,
 328                     SPECIAL(lower->kbtrans_buckybits, entry));
 329                 break;
 330 
 331         case SHIFTKEYS: {
 332                 uint_t shiftbit = 1 << (entry & 0x0F);
 333 
 334                 /* Modify toggle state (see toggle processing above) */
 335                 if (shiftbit & lower->kbtrans_keyboard->k_toggleshifts) {
 336                         if (newstate == KEY_RELEASED) {
 337                                 if (shiftbit == CAPSMASK) {
 338                                         lower->kbtrans_led_state &=
 339                                             ~LED_CAPS_LOCK;
 340 
 341                                         cb->kc_setled(lower->kbtrans_upper);
 342 
 343                                 } else if (shiftbit == NUMLOCKMASK) {
 344                                         lower->kbtrans_led_state &=
 345                                             ~LED_NUM_LOCK;
 346 
 347                                         cb->kc_setled(lower->kbtrans_upper);
 348                                 }


 360                                         cb->kc_setled(lower->kbtrans_upper);
 361                                 }
 362                                 lower->kbtrans_togglemask |= shiftbit;
 363                         }
 364                 }
 365 
 366                 if (newstate == KEY_RELEASED)
 367                         lower->kbtrans_shiftmask &= ~shiftbit;
 368                 else
 369                         lower->kbtrans_shiftmask |= shiftbit;
 370 
 371                 if (newstate == KEY_PRESSED) {
 372                         cb->kc_keypressed(lower->kbtrans_upper, entrytype, key,
 373                             entry);
 374                 }
 375 
 376                 break;
 377                 }
 378 
 379         case BUCKYBITS:
 380                 lower->kbtrans_buckybits ^= 1 << (entry & 0x0F);
 381 
 382                 if (newstate == KEY_PRESSED) {
 383                         cb->kc_keypressed(lower->kbtrans_upper, entrytype, key,
 384                             entry);
 385                 }
 386 
 387                 break;
 388 
 389         case FUNNY:
 390                 switch (entry) {
 391                 case NOP:
 392                         break;
 393 
 394                 case IDLE:
 395                         /* Fall thru into RESET code */
 396                         /* FALLTHRU */
 397                 case RESET:
 398                 case ERROR:
 399                         lower->kbtrans_shiftmask &=
 400                             lower->kbtrans_keyboard->k_idleshifts;


 446                 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key, entry);
 447 
 448                 break;
 449 
 450         /*
 451          * Remember when adding new entries that,
 452          * if they should NOT auto-repeat,
 453          * they should be put into the IF statement
 454          * just above this switch block.
 455          */
 456         case PADKEYS:
 457                 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key, entry);
 458 
 459                 break;
 460         }
 461 }
 462 
 463 /*
 464  * kbtrans_do_compose:
 465  *      Given a two key compose sequence, lookup the iso equivalent and put
 466  *      the result in the result_ptr.
 467  */
 468 static boolean_t
 469 kbtrans_do_compose(struct kbtrans_lower *lower, keymap_entry_t first_entry,
 470     keymap_entry_t second_entry, keymap_entry_t *result_ptr)


 471 {
 472         struct compose_sequence_t *ptr;
 473         keymap_entry_t tmp;
 474 
 475         /*
 476          * Validate the second keystroke.
 477          */
 478         if (second_entry >= ASCII_SET_SIZE)
 479                 return (B_FALSE);
 480 
 481         if (lower->kbtrans_compose_map[second_entry] < 0)
 482                 return (B_FALSE);
 483 
 484         /*
 485          * Get them in code order, rather than press order.
 486          */
 487         if (first_entry > second_entry) {
 488                 tmp = first_entry;
 489                 first_entry = second_entry;
 490                 second_entry = tmp;
 491         }
 492 
 493         ptr = lower->kbtrans_compose_table +
 494             lower->kbtrans_compose_map[first_entry];
 495 
 496         while (ptr->first == first_entry) {
 497                 if (ptr->second == second_entry) {
 498                         *result_ptr = ptr->utf8;
 499 
 500                         return (B_TRUE);
 501                 }
 502                 ptr++;
 503         }
 504         return (B_FALSE);
 505 }
 506 
 507 
 508 /*
 509  * kbtrans_find_entry:
 510  *      This routine finds the entry corresponding to the current shift
 511  *      state and keycode.
 512  */
 513 keymap_entry_t *
 514 kbtrans_find_entry(struct kbtrans_lower *lower, uint_t mask,

 515     kbtrans_key_t key_station)
 516 {
 517         register struct keyboard *kp;
 518         keymap_entry_t *km;
 519         struct exception_map *ex;
 520 
 521         kp = lower->kbtrans_keyboard;
 522 
 523         if (kp == NULL)
 524                 return (NULL);
 525 
 526         if (key_station < 0 || key_station >= kp->k_keymap_size)
 527                 return (NULL);
 528 
 529         ex = kp->k_except;
 530         if (ex != NULL) {
 531                 for (; ex->exc_care != 0; ex++) {
 532                         if ((mask & ex->exc_care) == ex->exc_mask &&
 533                             key_station == ex->exc_key)
 534                                 return (&ex->exc_entry);