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>


   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   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 #ifndef lint
  23 #ident  "%Z%%M% %I%     %E% SMI"
  24 #endif
  25 
  26 /*
  27  * Copyright (c) 1988 by Sun Microsystems, Inc.
  28  */
  29 
  30 #include <sys/types.h>
  31 #include <ctype.h>
  32 #include <stdio.h>
  33 #include <fcntl.h>
  34 #include <sys/kbd.h>
  35 #include <sys/kbio.h>
  36 #include <errno.h>
  37 
  38 typedef enum {
  39         SM_INVALID,     /* this shift mask is invalid for this keyboard */
  40         SM_NORMAL,      /* "normal", valid shift mask */
  41         SM_NUMLOCK,     /* "Num Lock" shift mask */
  42         SM_UP           /* "Up" shift mask */
  43 } smtype_t;
  44 


  49 } smentry_t;
  50 
  51 
  52 smentry_t shiftmasks[] = {
  53         { "base",       0,              SM_NORMAL },
  54         { "shift",      SHIFTMASK,      SM_NORMAL },
  55         { "caps",       CAPSMASK,       SM_NORMAL },
  56         { "ctrl",       CTRLMASK,       SM_NORMAL },
  57         { "altg",       ALTGRAPHMASK,   SM_NORMAL },
  58         { "numl",       NUMLOCKMASK,    SM_NUMLOCK },
  59         { "up",         UPMASK,         SM_UP },
  60 };
  61 
  62 #define NSHIFTS (sizeof (shiftmasks) / sizeof (shiftmasks[0]))
  63 
  64 static void     printentry(struct kiockeymap *kio);
  65 static void     printchar(int character, int delim);
  66 
  67 /*ARGSUSED*/
  68 int
  69 main(argc, argv)
  70         int argc;
  71         char **argv;
  72 {
  73         register int kbdfd;
  74         register int keystation;
  75         register int shift;
  76         int ktype;
  77         struct kiockeymap keyentry[NSHIFTS];
  78         register int allsame;
  79 
  80         if ((kbdfd = open("/dev/kbd", O_WRONLY)) < 0) {
  81                 perror("dumpkeys: /dev/kbd");
  82                 return (1);
  83         }
  84         if (ioctl(kbdfd, KIOCTYPE, &ktype) < 0) {
  85                 perror("dumpkeys: ioctl(KIOCTYPE)");
  86                 return (1);
  87         }
  88         /* if no keyboard detected, or ascii terminal, exit silently */
  89         if (ktype == KB_ASCII || ktype < 0)
  90                 exit(0);
  91 


 225         "top",                  /* not used */
 226         "cmd",                  /* reserved */
 227         "altgraph",
 228         "alt",
 229         "numlock",
 230 };
 231 
 232 #define NSHIFTKEYS      (sizeof (shiftkeys) / sizeof (shiftkeys[0]))
 233 
 234 static char *buckybits[] = {
 235         "metabit",
 236         "systembit",
 237 };
 238 
 239 #define NBUCKYBITS      (sizeof (buckybits) / sizeof (buckybits[0]))
 240 
 241 static char *funnies[] = {
 242         "nop",
 243         "oops",
 244         "hole",



 245         "reset",
 246         "error",
 247         "idle",
 248         "compose",
 249         "nonl",
 250 };
 251 
 252 #define NFUNNIES        (sizeof (funnies) / sizeof (funnies[0]))
 253 
 254 static char *fa_class[] = {
 255         "fa_umlaut",
 256         "fa_cflex",
 257         "fa_tilde",
 258         "fa_cedilla",
 259         "fa_acute",
 260         "fa_grave",









 261 };
 262 
 263 #define NFA_CLASS       (sizeof (fa_class) / sizeof (fa_class[0]))
 264 
 265 typedef struct {
 266         char    *string;
 267         char    *name;
 268 } builtin_string_t;
 269 
 270 builtin_string_t builtin_strings[] = {
 271         { "\033[H",     "homearrow" },
 272         { "\033[A",     "uparrow" },
 273         { "\033[B",     "downarrow" },
 274         { "\033[D",     "leftarrow" },
 275         { "\033[C",     "rightarrow" },
 276 };
 277 
 278 #define NBUILTIN_STRINGS        (sizeof (builtin_strings) / \
 279                                         sizeof (builtin_strings[0]))
 280 


 294         "padminus",
 295         "padsep",
 296         "pad7",
 297         "pad8",
 298         "pad9",
 299         "padplus",
 300         "pad4",
 301         "pad5",
 302         "pad6",
 303         "pad1",
 304         "pad2",
 305         "pad3",
 306         "pad0",
 307         "paddot",
 308         "padenter",
 309 };
 310 
 311 #define NPADKEYS        (sizeof (padkeys) / sizeof (padkeys[0]))
 312 
 313 static void
 314 printentry(kio)
 315         register struct kiockeymap *kio;
 316 {
 317         register int entry = (kio->kio_entry & 0x1F);
 318         register int fkeyset;
 319         register int i;
 320         register int c;
 321 
 322         switch (kio->kio_entry >> 8) {
 323 
 324         case 0x0:
 325                 if (kio->kio_entry == '"')
 326                         (void) printf("'\"'");  /* special case */
 327                 else if (kio->kio_entry == ' ')
 328                         (void) printf("' '");   /* special case */
 329                 else
 330                         printchar((int)kio->kio_entry, '\'');
 331                 break;
 332 
 333         case SHIFTKEYS >> 8:
 334                 if (entry < NSHIFTKEYS)
 335                         (void) printf("shiftkeys+%s", shiftkeys[entry]);
 336                 else
 337                         (void) printf("%#4x", kio->kio_entry);
 338                 break;
 339 
 340         case BUCKYBITS >> 8:
 341                 if (entry < NBUCKYBITS)
 342                         (void) printf("buckybits+%s", buckybits[entry]);
 343                 else
 344                         (void) printf("%#4x", kio->kio_entry);
 345                 break;
 346 
 347         case FUNNY >> 8:
 348                 if (entry < NFUNNIES)
 349                         (void) printf("%s", funnies[entry]);
 350                 else
 351                         (void) printf("%#4x", kio->kio_entry);
 352                 break;
 353 
 354         case FA_CLASS >> 8:
 355                 if (entry < NFA_CLASS)
 356                         (void) printf("%s", fa_class[entry]);
 357                 else
 358                         (void) printf("%#4x", kio->kio_entry);
 359                 break;
 360 
 361         case STRING >> 8:
 362                 if (entry < NBUILTIN_STRINGS && strncmp(kio->kio_string,
 363                         builtin_strings[entry].string, KTAB_STRLEN) == 0)
 364                         (void) printf("string+%s", builtin_strings[entry].name);
 365                 else {
 366                         (void) printf("\"");
 367                         for (i = 0;
 368                             i < KTAB_STRLEN && (c = kio->kio_string[i]) != '\0';
 369                             i++)
 370                                 printchar(c, '"');
 371                         (void) printf("\"");
 372                 }
 373                 break;
 374 
 375         case FUNCKEYS >> 8:
 376                 fkeyset = (int)(kio->kio_entry & 0xF0) >> 4;
 377                 if (fkeyset < NFKEYSETS)
 378                         (void) printf("%s(%d)", fkeysets[fkeyset],
 379                                         (entry&0x0F) + 1);
 380                 else
 381                         (void) printf("%#4x", kio->kio_entry);
 382                 break;
 383 
 384         case PADKEYS >> 8:
 385                 if (entry < NPADKEYS)
 386                         (void) printf("%s", padkeys[entry]);
 387                 else
 388                         (void) printf("%#4x", kio->kio_entry);
 389                 break;
 390 
 391         default:
 392                 (void) printf("%#4x", kio->kio_entry);
 393                 break;
 394         }
 395 }
 396 
 397 static void
 398 printchar(character, delim)
 399         int character;
 400         int delim;
 401 {
 402         switch (character) {
 403 
 404         case '\n':
 405                 (void) printf("'\\n'");
 406                 break;
 407 
 408         case '\t':
 409                 (void) printf("'\\t'");
 410                 break;
 411 
 412         case '\b':
 413                 (void) printf("'\\b'");
 414                 break;
 415 
 416         case '\r':
 417                 (void) printf("'\\r'");
 418                 break;
 419 
 420         case '\v':
 421                 (void) printf("'\\v'");
 422                 break;
 423 
 424         case '\\':
 425                 (void) printf("'\\\\'");
 426                 break;
 427 
 428         default:
 429                 if (isprint(character)) {
 430                         if (character == delim)
 431                                 (void) printf("'\\'");
 432                         (void) printf("%c", character);
 433                 } else {
 434                         if (character < 040)
 435                                 (void) printf("^%c", character + 0100);
 436                         else
 437                                 (void) printf("'\\%.3o'", character);


 438                 }
 439                 break;
 440         }
 441 }


   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   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 /*
  24  * Copyright (c) 1988 by Sun Microsystems, Inc.
  25  */
  26 
  27 #include <sys/types.h>
  28 #include <ctype.h>
  29 #include <stdio.h>
  30 #include <fcntl.h>
  31 #include <sys/kbd.h>
  32 #include <sys/kbio.h>
  33 #include <errno.h>
  34 
  35 typedef enum {
  36         SM_INVALID,     /* this shift mask is invalid for this keyboard */
  37         SM_NORMAL,      /* "normal", valid shift mask */
  38         SM_NUMLOCK,     /* "Num Lock" shift mask */
  39         SM_UP           /* "Up" shift mask */
  40 } smtype_t;
  41 


  46 } smentry_t;
  47 
  48 
  49 smentry_t shiftmasks[] = {
  50         { "base",       0,              SM_NORMAL },
  51         { "shift",      SHIFTMASK,      SM_NORMAL },
  52         { "caps",       CAPSMASK,       SM_NORMAL },
  53         { "ctrl",       CTRLMASK,       SM_NORMAL },
  54         { "altg",       ALTGRAPHMASK,   SM_NORMAL },
  55         { "numl",       NUMLOCKMASK,    SM_NUMLOCK },
  56         { "up",         UPMASK,         SM_UP },
  57 };
  58 
  59 #define NSHIFTS (sizeof (shiftmasks) / sizeof (shiftmasks[0]))
  60 
  61 static void     printentry(struct kiockeymap *kio);
  62 static void     printchar(int character, int delim);
  63 
  64 /*ARGSUSED*/
  65 int
  66 main(int argc, char **argv)


  67 {
  68         register int kbdfd;
  69         register int keystation;
  70         register int shift;
  71         int ktype;
  72         struct kiockeymap keyentry[NSHIFTS];
  73         register int allsame;
  74 
  75         if ((kbdfd = open("/dev/kbd", O_WRONLY)) < 0) {
  76                 perror("dumpkeys: /dev/kbd");
  77                 return (1);
  78         }
  79         if (ioctl(kbdfd, KIOCTYPE, &ktype) < 0) {
  80                 perror("dumpkeys: ioctl(KIOCTYPE)");
  81                 return (1);
  82         }
  83         /* if no keyboard detected, or ascii terminal, exit silently */
  84         if (ktype == KB_ASCII || ktype < 0)
  85                 exit(0);
  86 


 220         "top",                  /* not used */
 221         "cmd",                  /* reserved */
 222         "altgraph",
 223         "alt",
 224         "numlock",
 225 };
 226 
 227 #define NSHIFTKEYS      (sizeof (shiftkeys) / sizeof (shiftkeys[0]))
 228 
 229 static char *buckybits[] = {
 230         "metabit",
 231         "systembit",
 232 };
 233 
 234 #define NBUCKYBITS      (sizeof (buckybits) / sizeof (buckybits[0]))
 235 
 236 static char *funnies[] = {
 237         "nop",
 238         "oops",
 239         "hole",
 240         "",                     /* not used */
 241         "",                     /* not used */
 242         "",                     /* not used */
 243         "reset",
 244         "error",
 245         "idle",
 246         "compose",
 247         "nonl",
 248 };
 249 
 250 #define NFUNNIES        (sizeof (funnies) / sizeof (funnies[0]))
 251 
 252 static char *fa_class[] = {
 253         "fa_umlaut",
 254         "fa_cflex",
 255         "fa_tilde",
 256         "fa_cedilla",
 257         "fa_acute",
 258         "fa_grave",
 259         "fa_macron",
 260         "fa_breve",
 261         "fa_dot",
 262         "fa_slash",
 263         "fa_ring",
 264         "fa_apostrophe",
 265         "fa_dacute",
 266         "fa_ogonek",
 267         "fa_caron"
 268 };
 269 
 270 #define NFA_CLASS       (sizeof (fa_class) / sizeof (fa_class[0]))
 271 
 272 typedef struct {
 273         char    *string;
 274         char    *name;
 275 } builtin_string_t;
 276 
 277 builtin_string_t builtin_strings[] = {
 278         { "\033[H",     "homearrow" },
 279         { "\033[A",     "uparrow" },
 280         { "\033[B",     "downarrow" },
 281         { "\033[D",     "leftarrow" },
 282         { "\033[C",     "rightarrow" },
 283 };
 284 
 285 #define NBUILTIN_STRINGS        (sizeof (builtin_strings) / \
 286                                         sizeof (builtin_strings[0]))
 287 


 301         "padminus",
 302         "padsep",
 303         "pad7",
 304         "pad8",
 305         "pad9",
 306         "padplus",
 307         "pad4",
 308         "pad5",
 309         "pad6",
 310         "pad1",
 311         "pad2",
 312         "pad3",
 313         "pad0",
 314         "paddot",
 315         "padenter",
 316 };
 317 
 318 #define NPADKEYS        (sizeof (padkeys) / sizeof (padkeys[0]))
 319 
 320 static void
 321 printentry(struct kiockeymap *kio)

 322 {
 323         int entry = (kio->kio_entry & 0x1F);
 324         int fkeyset;
 325         int i;
 326         int c;
 327 
 328         switch (KEYFLAGS(kio->kio_entry)) {
 329 
 330         case 0x0:
 331                 if (kio->kio_entry == '"')
 332                         (void) printf("'\"'");  /* special case */
 333                 else if (kio->kio_entry == ' ')
 334                         (void) printf("' '");   /* special case */
 335                 else
 336                         printchar((int)kio->kio_entry, '\'');
 337                 break;
 338 
 339         case SHIFTKEYS:
 340                 if (entry < NSHIFTKEYS)
 341                         (void) printf("shiftkeys+%s", shiftkeys[entry]);
 342                 else
 343                         (void) printf("%#4x", kio->kio_entry);
 344                 break;
 345 
 346         case BUCKYBITS:
 347                 if (entry < NBUCKYBITS)
 348                         (void) printf("buckybits+%s", buckybits[entry]);
 349                 else
 350                         (void) printf("%#4x", kio->kio_entry);
 351                 break;
 352 
 353         case FUNNY:
 354                 if (entry < NFUNNIES)
 355                         (void) printf("%s", funnies[entry]);
 356                 else
 357                         (void) printf("%#4x", kio->kio_entry);
 358                 break;
 359 
 360         case FA_CLASS:
 361                 if (entry < NFA_CLASS)
 362                         (void) printf("%s", fa_class[entry]);
 363                 else
 364                         (void) printf("%#4x", kio->kio_entry);
 365                 break;
 366 
 367         case STRING:
 368                 if (entry < NBUILTIN_STRINGS && strncmp(kio->kio_string,
 369                     builtin_strings[entry].string, KTAB_STRLEN) == 0)
 370                         (void) printf("string+%s", builtin_strings[entry].name);
 371                 else {
 372                         (void) printf("\"");
 373                         for (i = 0;
 374                             i < KTAB_STRLEN && (c = kio->kio_string[i]) != '\0';
 375                             i++)
 376                                 printchar(c, '"');
 377                         (void) printf("\"");
 378                 }
 379                 break;
 380 
 381         case FUNCKEYS:
 382                 fkeyset = (int)(kio->kio_entry & 0xF0) >> 4;
 383                 if (fkeyset < NFKEYSETS)
 384                         (void) printf("%s(%d)", fkeysets[fkeyset],
 385                             (entry & 0x0F) + 1);
 386                 else
 387                         (void) printf("%#4x", kio->kio_entry);
 388                 break;
 389 
 390         case PADKEYS:
 391                 if (entry < NPADKEYS)
 392                         (void) printf("%s", padkeys[entry]);
 393                 else
 394                         (void) printf("%#4x", kio->kio_entry);
 395                 break;
 396 
 397         default:
 398                 (void) printf("%#4x", kio->kio_entry);
 399                 break;
 400         }
 401 }
 402 
 403 static void
 404 printchar(int character, int delim)


 405 {
 406         switch (character) {
 407 
 408         case '\n':
 409                 (void) printf("'\\n'");
 410                 break;
 411 
 412         case '\t':
 413                 (void) printf("'\\t'");
 414                 break;
 415 
 416         case '\b':
 417                 (void) printf("'\\b'");
 418                 break;
 419 
 420         case '\r':
 421                 (void) printf("'\\r'");
 422                 break;
 423 
 424         case '\v':
 425                 (void) printf("'\\v'");
 426                 break;
 427 
 428         case '\\':
 429                 (void) printf("'\\\\'");
 430                 break;
 431 
 432         default:
 433                 if (isprint(character)) {
 434                         if (character == delim)
 435                                 (void) printf("'\\'");
 436                         (void) printf("%c", character);
 437                 } else {
 438                         if (character < 040)
 439                                 (void) printf("^%c", character + 0100);
 440                         else if (character <= 0xff)
 441                                 (void) printf("'\\%.3o'", character);
 442                         else
 443                                 (void) printf("%#4x", character);
 444                 }
 445                 break;
 446         }
 447 }