uboot/drivers/video/vidconsole-uclass.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2015 Google, Inc
   4 * (C) Copyright 2001-2015
   5 * DENX Software Engineering -- wd@denx.de
   6 * Compulab Ltd - http://compulab.co.il/
   7 * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
   8 */
   9
  10#define LOG_CATEGORY UCLASS_VIDEO_CONSOLE
  11
  12#include <common.h>
  13#include <command.h>
  14#include <console.h>
  15#include <log.h>
  16#include <dm.h>
  17#include <video.h>
  18#include <video_console.h>
  19#include <video_font.h>         /* Bitmap font for code page 437 */
  20#include <linux/ctype.h>
  21
  22/*
  23 * Structure to describe a console color
  24 */
  25struct vid_rgb {
  26        u32 r;
  27        u32 g;
  28        u32 b;
  29};
  30
  31/* By default we scroll by a single line */
  32#ifndef CONFIG_CONSOLE_SCROLL_LINES
  33#define CONFIG_CONSOLE_SCROLL_LINES 1
  34#endif
  35
  36int vidconsole_putc_xy(struct udevice *dev, uint x, uint y, char ch)
  37{
  38        struct vidconsole_ops *ops = vidconsole_get_ops(dev);
  39
  40        if (!ops->putc_xy)
  41                return -ENOSYS;
  42        return ops->putc_xy(dev, x, y, ch);
  43}
  44
  45int vidconsole_move_rows(struct udevice *dev, uint rowdst, uint rowsrc,
  46                         uint count)
  47{
  48        struct vidconsole_ops *ops = vidconsole_get_ops(dev);
  49
  50        if (!ops->move_rows)
  51                return -ENOSYS;
  52        return ops->move_rows(dev, rowdst, rowsrc, count);
  53}
  54
  55int vidconsole_set_row(struct udevice *dev, uint row, int clr)
  56{
  57        struct vidconsole_ops *ops = vidconsole_get_ops(dev);
  58
  59        if (!ops->set_row)
  60                return -ENOSYS;
  61        return ops->set_row(dev, row, clr);
  62}
  63
  64static int vidconsole_entry_start(struct udevice *dev)
  65{
  66        struct vidconsole_ops *ops = vidconsole_get_ops(dev);
  67
  68        if (!ops->entry_start)
  69                return -ENOSYS;
  70        return ops->entry_start(dev);
  71}
  72
  73/* Move backwards one space */
  74static int vidconsole_back(struct udevice *dev)
  75{
  76        struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
  77        struct vidconsole_ops *ops = vidconsole_get_ops(dev);
  78        int ret;
  79
  80        if (ops->backspace) {
  81                ret = ops->backspace(dev);
  82                if (ret != -ENOSYS)
  83                        return ret;
  84        }
  85
  86        priv->xcur_frac -= VID_TO_POS(priv->x_charsize);
  87        if (priv->xcur_frac < priv->xstart_frac) {
  88                priv->xcur_frac = (priv->cols - 1) *
  89                        VID_TO_POS(priv->x_charsize);
  90                priv->ycur -= priv->y_charsize;
  91                if (priv->ycur < 0)
  92                        priv->ycur = 0;
  93        }
  94        return video_sync(dev->parent, false);
  95}
  96
  97/* Move to a newline, scrolling the display if necessary */
  98static void vidconsole_newline(struct udevice *dev)
  99{
 100        struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
 101        struct udevice *vid_dev = dev->parent;
 102        struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
 103        const int rows = CONFIG_CONSOLE_SCROLL_LINES;
 104        int i, ret;
 105
 106        priv->xcur_frac = priv->xstart_frac;
 107        priv->ycur += priv->y_charsize;
 108
 109        /* Check if we need to scroll the terminal */
 110        if ((priv->ycur + priv->y_charsize) / priv->y_charsize > priv->rows) {
 111                vidconsole_move_rows(dev, 0, rows, priv->rows - rows);
 112                for (i = 0; i < rows; i++)
 113                        vidconsole_set_row(dev, priv->rows - i - 1,
 114                                           vid_priv->colour_bg);
 115                priv->ycur -= rows * priv->y_charsize;
 116        }
 117        priv->last_ch = 0;
 118
 119        ret = video_sync(dev->parent, false);
 120        if (ret) {
 121#ifdef DEBUG
 122                console_puts_select_stderr(true, "[vc err: video_sync]");
 123#endif
 124        }
 125}
 126
 127static const struct vid_rgb colors[VID_COLOR_COUNT] = {
 128        { 0x00, 0x00, 0x00 },  /* black */
 129        { 0xc0, 0x00, 0x00 },  /* red */
 130        { 0x00, 0xc0, 0x00 },  /* green */
 131        { 0xc0, 0x60, 0x00 },  /* brown */
 132        { 0x00, 0x00, 0xc0 },  /* blue */
 133        { 0xc0, 0x00, 0xc0 },  /* magenta */
 134        { 0x00, 0xc0, 0xc0 },  /* cyan */
 135        { 0xc0, 0xc0, 0xc0 },  /* light gray */
 136        { 0x80, 0x80, 0x80 },  /* gray */
 137        { 0xff, 0x00, 0x00 },  /* bright red */
 138        { 0x00, 0xff, 0x00 },  /* bright green */
 139        { 0xff, 0xff, 0x00 },  /* yellow */
 140        { 0x00, 0x00, 0xff },  /* bright blue */
 141        { 0xff, 0x00, 0xff },  /* bright magenta */
 142        { 0x00, 0xff, 0xff },  /* bright cyan */
 143        { 0xff, 0xff, 0xff },  /* white */
 144};
 145
 146u32 vid_console_color(struct video_priv *priv, unsigned int idx)
 147{
 148        switch (priv->bpix) {
 149        case VIDEO_BPP16:
 150                if (CONFIG_IS_ENABLED(VIDEO_BPP16)) {
 151                        return ((colors[idx].r >> 3) << 11) |
 152                               ((colors[idx].g >> 2) <<  5) |
 153                               ((colors[idx].b >> 3) <<  0);
 154                }
 155                break;
 156        case VIDEO_BPP32:
 157                if (CONFIG_IS_ENABLED(VIDEO_BPP32)) {
 158                        if (priv->format == VIDEO_X2R10G10B10)
 159                                return (colors[idx].r << 22) |
 160                                       (colors[idx].g << 12) |
 161                                       (colors[idx].b <<  2);
 162                        else
 163                                return (colors[idx].r << 16) |
 164                                       (colors[idx].g <<  8) |
 165                                       (colors[idx].b <<  0);
 166                }
 167                break;
 168        default:
 169                break;
 170        }
 171
 172        /*
 173         * For unknown bit arrangements just support
 174         * black and white.
 175         */
 176        if (idx)
 177                return 0xffffff; /* white */
 178
 179        return 0x000000; /* black */
 180}
 181
 182static char *parsenum(char *s, int *num)
 183{
 184        char *end;
 185        *num = simple_strtol(s, &end, 10);
 186        return end;
 187}
 188
 189/**
 190 * set_cursor_position() - set cursor position
 191 *
 192 * @priv:       private data of the video console
 193 * @row:        new row
 194 * @col:        new column
 195 */
 196static void set_cursor_position(struct vidconsole_priv *priv, int row, int col)
 197{
 198        /*
 199         * Ensure we stay in the bounds of the screen.
 200         */
 201        if (row >= priv->rows)
 202                row = priv->rows - 1;
 203        if (col >= priv->cols)
 204                col = priv->cols - 1;
 205
 206        priv->ycur = row * priv->y_charsize;
 207        priv->xcur_frac = priv->xstart_frac +
 208                          VID_TO_POS(col * priv->x_charsize);
 209}
 210
 211/**
 212 * get_cursor_position() - get cursor position
 213 *
 214 * @priv:       private data of the video console
 215 * @row:        row
 216 * @col:        column
 217 */
 218static void get_cursor_position(struct vidconsole_priv *priv,
 219                                int *row, int *col)
 220{
 221        *row = priv->ycur / priv->y_charsize;
 222        *col = VID_TO_PIXEL(priv->xcur_frac - priv->xstart_frac) /
 223               priv->x_charsize;
 224}
 225
 226/*
 227 * Process a character while accumulating an escape string.  Chars are
 228 * accumulated into escape_buf until the end of escape sequence is
 229 * found, at which point the sequence is parsed and processed.
 230 */
 231static void vidconsole_escape_char(struct udevice *dev, char ch)
 232{
 233        struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
 234
 235        if (!IS_ENABLED(CONFIG_VIDEO_ANSI))
 236                goto error;
 237
 238        /* Sanity checking for bogus ESC sequences: */
 239        if (priv->escape_len >= sizeof(priv->escape_buf))
 240                goto error;
 241        if (priv->escape_len == 0) {
 242                switch (ch) {
 243                case '7':
 244                        /* Save cursor position */
 245                        get_cursor_position(priv, &priv->row_saved,
 246                                            &priv->col_saved);
 247                        priv->escape = 0;
 248
 249                        return;
 250                case '8': {
 251                        /* Restore cursor position */
 252                        int row = priv->row_saved;
 253                        int col = priv->col_saved;
 254
 255                        set_cursor_position(priv, row, col);
 256                        priv->escape = 0;
 257                        return;
 258                }
 259                case '[':
 260                        break;
 261                default:
 262                        goto error;
 263                }
 264        }
 265
 266        priv->escape_buf[priv->escape_len++] = ch;
 267
 268        /*
 269         * Escape sequences are terminated by a letter, so keep
 270         * accumulating until we get one:
 271         */
 272        if (!isalpha(ch))
 273                return;
 274
 275        /*
 276         * clear escape mode first, otherwise things will get highly
 277         * surprising if you hit any debug prints that come back to
 278         * this console.
 279         */
 280        priv->escape = 0;
 281
 282        switch (ch) {
 283        case 'A':
 284        case 'B':
 285        case 'C':
 286        case 'D':
 287        case 'E':
 288        case 'F': {
 289                int row, col, num;
 290                char *s = priv->escape_buf;
 291
 292                /*
 293                 * Cursor up/down: [%dA, [%dB, [%dE, [%dF
 294                 * Cursor left/right: [%dD, [%dC
 295                 */
 296                s++;    /* [ */
 297                s = parsenum(s, &num);
 298                if (num == 0)                   /* No digit in sequence ... */
 299                        num = 1;                /* ... means "move by 1". */
 300
 301                get_cursor_position(priv, &row, &col);
 302                if (ch == 'A' || ch == 'F')
 303                        row -= num;
 304                if (ch == 'C')
 305                        col += num;
 306                if (ch == 'D')
 307                        col -= num;
 308                if (ch == 'B' || ch == 'E')
 309                        row += num;
 310                if (ch == 'E' || ch == 'F')
 311                        col = 0;
 312                if (col < 0)
 313                        col = 0;
 314                if (row < 0)
 315                        row = 0;
 316                /* Right and bottom overflows are handled in the callee. */
 317                set_cursor_position(priv, row, col);
 318                break;
 319        }
 320        case 'H':
 321        case 'f': {
 322                int row, col;
 323                char *s = priv->escape_buf;
 324
 325                /*
 326                 * Set cursor position: [%d;%df or [%d;%dH
 327                 */
 328                s++;    /* [ */
 329                s = parsenum(s, &row);
 330                s++;    /* ; */
 331                s = parsenum(s, &col);
 332
 333                /*
 334                 * Video origin is [0, 0], terminal origin is [1, 1].
 335                 */
 336                if (row)
 337                        --row;
 338                if (col)
 339                        --col;
 340
 341                set_cursor_position(priv, row, col);
 342
 343                break;
 344        }
 345        case 'J': {
 346                int mode;
 347
 348                /*
 349                 * Clear part/all screen:
 350                 *   [J or [0J - clear screen from cursor down
 351                 *   [1J       - clear screen from cursor up
 352                 *   [2J       - clear entire screen
 353                 *
 354                 * TODO we really only handle entire-screen case, others
 355                 * probably require some additions to video-uclass (and
 356                 * are not really needed yet by efi_console)
 357                 */
 358                parsenum(priv->escape_buf + 1, &mode);
 359
 360                if (mode == 2) {
 361                        int ret;
 362
 363                        video_clear(dev->parent);
 364                        ret = video_sync(dev->parent, false);
 365                        if (ret) {
 366#ifdef DEBUG
 367                                console_puts_select_stderr(true, "[vc err: video_sync]");
 368#endif
 369                        }
 370                        priv->ycur = 0;
 371                        priv->xcur_frac = priv->xstart_frac;
 372                } else {
 373                        debug("unsupported clear mode: %d\n", mode);
 374                }
 375                break;
 376        }
 377        case 'K': {
 378                struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
 379                int mode;
 380
 381                /*
 382                 * Clear (parts of) current line
 383                 *   [0K       - clear line to end
 384                 *   [2K       - clear entire line
 385                 */
 386                parsenum(priv->escape_buf + 1, &mode);
 387
 388                if (mode == 2) {
 389                        int row, col;
 390
 391                        get_cursor_position(priv, &row, &col);
 392                        vidconsole_set_row(dev, row, vid_priv->colour_bg);
 393                }
 394                break;
 395        }
 396        case 'm': {
 397                struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
 398                char *s = priv->escape_buf;
 399                char *end = &priv->escape_buf[priv->escape_len];
 400
 401                /*
 402                 * Set graphics mode: [%d;...;%dm
 403                 *
 404                 * Currently only supports the color attributes:
 405                 *
 406                 * Foreground Colors:
 407                 *
 408                 *   30 Black
 409                 *   31 Red
 410                 *   32 Green
 411                 *   33 Yellow
 412                 *   34 Blue
 413                 *   35 Magenta
 414                 *   36 Cyan
 415                 *   37 White
 416                 *
 417                 * Background Colors:
 418                 *
 419                 *   40 Black
 420                 *   41 Red
 421                 *   42 Green
 422                 *   43 Yellow
 423                 *   44 Blue
 424                 *   45 Magenta
 425                 *   46 Cyan
 426                 *   47 White
 427                 */
 428
 429                s++;    /* [ */
 430                while (s < end) {
 431                        int val;
 432
 433                        s = parsenum(s, &val);
 434                        s++;
 435
 436                        switch (val) {
 437                        case 0:
 438                                /* all attributes off */
 439                                video_set_default_colors(dev->parent, false);
 440                                break;
 441                        case 1:
 442                                /* bold */
 443                                vid_priv->fg_col_idx |= 8;
 444                                vid_priv->colour_fg = vid_console_color(
 445                                                vid_priv, vid_priv->fg_col_idx);
 446                                break;
 447                        case 7:
 448                                /* reverse video */
 449                                vid_priv->colour_fg = vid_console_color(
 450                                                vid_priv, vid_priv->bg_col_idx);
 451                                vid_priv->colour_bg = vid_console_color(
 452                                                vid_priv, vid_priv->fg_col_idx);
 453                                break;
 454                        case 30 ... 37:
 455                                /* foreground color */
 456                                vid_priv->fg_col_idx &= ~7;
 457                                vid_priv->fg_col_idx |= val - 30;
 458                                vid_priv->colour_fg = vid_console_color(
 459                                                vid_priv, vid_priv->fg_col_idx);
 460                                break;
 461                        case 40 ... 47:
 462                                /* background color, also mask the bold bit */
 463                                vid_priv->bg_col_idx &= ~0xf;
 464                                vid_priv->bg_col_idx |= val - 40;
 465                                vid_priv->colour_bg = vid_console_color(
 466                                                vid_priv, vid_priv->bg_col_idx);
 467                                break;
 468                        default:
 469                                /* ignore unsupported SGR parameter */
 470                                break;
 471                        }
 472                }
 473
 474                break;
 475        }
 476        default:
 477                debug("unrecognized escape sequence: %*s\n",
 478                      priv->escape_len, priv->escape_buf);
 479        }
 480
 481        return;
 482
 483error:
 484        /* something went wrong, just revert to normal mode: */
 485        priv->escape = 0;
 486}
 487
 488/* Put that actual character on the screen (using the CP437 code page). */
 489static int vidconsole_output_glyph(struct udevice *dev, char ch)
 490{
 491        struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
 492        int ret;
 493
 494        /*
 495         * Failure of this function normally indicates an unsupported
 496         * colour depth. Check this and return an error to help with
 497         * diagnosis.
 498         */
 499        ret = vidconsole_putc_xy(dev, priv->xcur_frac, priv->ycur, ch);
 500        if (ret == -EAGAIN) {
 501                vidconsole_newline(dev);
 502                ret = vidconsole_putc_xy(dev, priv->xcur_frac, priv->ycur, ch);
 503        }
 504        if (ret < 0)
 505                return ret;
 506        priv->xcur_frac += ret;
 507        priv->last_ch = ch;
 508        if (priv->xcur_frac >= priv->xsize_frac)
 509                vidconsole_newline(dev);
 510
 511        return 0;
 512}
 513
 514int vidconsole_put_char(struct udevice *dev, char ch)
 515{
 516        struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
 517        int ret;
 518
 519        if (priv->escape) {
 520                vidconsole_escape_char(dev, ch);
 521                return 0;
 522        }
 523
 524        switch (ch) {
 525        case '\x1b':
 526                priv->escape_len = 0;
 527                priv->escape = 1;
 528                break;
 529        case '\a':
 530                /* beep */
 531                break;
 532        case '\r':
 533                priv->xcur_frac = priv->xstart_frac;
 534                break;
 535        case '\n':
 536                vidconsole_newline(dev);
 537                vidconsole_entry_start(dev);
 538                break;
 539        case '\t':      /* Tab (8 chars alignment) */
 540                priv->xcur_frac = ((priv->xcur_frac / priv->tab_width_frac)
 541                                + 1) * priv->tab_width_frac;
 542
 543                if (priv->xcur_frac >= priv->xsize_frac)
 544                        vidconsole_newline(dev);
 545                break;
 546        case '\b':
 547                vidconsole_back(dev);
 548                priv->last_ch = 0;
 549                break;
 550        default:
 551                ret = vidconsole_output_glyph(dev, ch);
 552                if (ret < 0)
 553                        return ret;
 554                break;
 555        }
 556
 557        return 0;
 558}
 559
 560int vidconsole_put_string(struct udevice *dev, const char *str)
 561{
 562        const char *s;
 563        int ret;
 564
 565        for (s = str; *s; s++) {
 566                ret = vidconsole_put_char(dev, *s);
 567                if (ret)
 568                        return ret;
 569        }
 570
 571        return 0;
 572}
 573
 574static void vidconsole_putc(struct stdio_dev *sdev, const char ch)
 575{
 576        struct udevice *dev = sdev->priv;
 577        int ret;
 578
 579        ret = vidconsole_put_char(dev, ch);
 580        if (ret) {
 581#ifdef DEBUG
 582                console_puts_select_stderr(true, "[vc err: putc]");
 583#endif
 584        }
 585        ret = video_sync(dev->parent, false);
 586        if (ret) {
 587#ifdef DEBUG
 588                console_puts_select_stderr(true, "[vc err: video_sync]");
 589#endif
 590        }
 591}
 592
 593static void vidconsole_puts(struct stdio_dev *sdev, const char *s)
 594{
 595        struct udevice *dev = sdev->priv;
 596        int ret;
 597
 598        ret = vidconsole_put_string(dev, s);
 599        if (ret) {
 600#ifdef DEBUG
 601                char str[30];
 602
 603                snprintf(str, sizeof(str), "[vc err: puts %d]", ret);
 604                console_puts_select_stderr(true, str);
 605#endif
 606        }
 607        ret = video_sync(dev->parent, false);
 608        if (ret) {
 609#ifdef DEBUG
 610                console_puts_select_stderr(true, "[vc err: video_sync]");
 611#endif
 612        }
 613}
 614
 615/* Set up the number of rows and colours (rotated drivers override this) */
 616static int vidconsole_pre_probe(struct udevice *dev)
 617{
 618        struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
 619        struct udevice *vid = dev->parent;
 620        struct video_priv *vid_priv = dev_get_uclass_priv(vid);
 621
 622        priv->xsize_frac = VID_TO_POS(vid_priv->xsize);
 623
 624        return 0;
 625}
 626
 627/* Register the device with stdio */
 628static int vidconsole_post_probe(struct udevice *dev)
 629{
 630        struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
 631        struct stdio_dev *sdev = &priv->sdev;
 632
 633        if (!priv->tab_width_frac)
 634                priv->tab_width_frac = VID_TO_POS(priv->x_charsize) * 8;
 635
 636        if (dev_seq(dev)) {
 637                snprintf(sdev->name, sizeof(sdev->name), "vidconsole%d",
 638                         dev_seq(dev));
 639        } else {
 640                strcpy(sdev->name, "vidconsole");
 641        }
 642
 643        sdev->flags = DEV_FLAGS_OUTPUT;
 644        sdev->putc = vidconsole_putc;
 645        sdev->puts = vidconsole_puts;
 646        sdev->priv = dev;
 647
 648        return stdio_register(sdev);
 649}
 650
 651UCLASS_DRIVER(vidconsole) = {
 652        .id             = UCLASS_VIDEO_CONSOLE,
 653        .name           = "vidconsole0",
 654        .pre_probe      = vidconsole_pre_probe,
 655        .post_probe     = vidconsole_post_probe,
 656        .per_device_auto        = sizeof(struct vidconsole_priv),
 657};
 658
 659#ifdef CONFIG_VIDEO_COPY
 660int vidconsole_sync_copy(struct udevice *dev, void *from, void *to)
 661{
 662        struct udevice *vid = dev_get_parent(dev);
 663
 664        return video_sync_copy(vid, from, to);
 665}
 666
 667int vidconsole_memmove(struct udevice *dev, void *dst, const void *src,
 668                       int size)
 669{
 670        memmove(dst, src, size);
 671        return vidconsole_sync_copy(dev, dst, dst + size);
 672}
 673#endif
 674
 675#if CONFIG_IS_ENABLED(CMD_VIDCONSOLE)
 676void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row)
 677{
 678        struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
 679        struct udevice *vid_dev = dev->parent;
 680        struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
 681
 682        col *= priv->x_charsize;
 683        row *= priv->y_charsize;
 684        priv->xcur_frac = VID_TO_POS(min_t(short, col, vid_priv->xsize - 1));
 685        priv->xstart_frac = priv->xcur_frac;
 686        priv->ycur = min_t(short, row, vid_priv->ysize - 1);
 687}
 688
 689static int do_video_setcursor(struct cmd_tbl *cmdtp, int flag, int argc,
 690                              char *const argv[])
 691{
 692        unsigned int col, row;
 693        struct udevice *dev;
 694
 695        if (argc != 3)
 696                return CMD_RET_USAGE;
 697
 698        if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev))
 699                return CMD_RET_FAILURE;
 700        col = dectoul(argv[1], NULL);
 701        row = dectoul(argv[2], NULL);
 702        vidconsole_position_cursor(dev, col, row);
 703
 704        return 0;
 705}
 706
 707static int do_video_puts(struct cmd_tbl *cmdtp, int flag, int argc,
 708                         char *const argv[])
 709{
 710        struct udevice *dev;
 711        const char *s;
 712
 713        if (argc != 2)
 714                return CMD_RET_USAGE;
 715
 716        if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev))
 717                return CMD_RET_FAILURE;
 718        for (s = argv[1]; *s; s++)
 719                vidconsole_put_char(dev, *s);
 720
 721        return video_sync(dev->parent, false);
 722}
 723
 724U_BOOT_CMD(
 725        setcurs, 3,     1,      do_video_setcursor,
 726        "set cursor position within screen",
 727        "    <col> <row> in character"
 728);
 729
 730U_BOOT_CMD(
 731        lcdputs, 2,     1,      do_video_puts,
 732        "print string on video framebuffer",
 733        "    <string>"
 734);
 735#endif /* CONFIG_IS_ENABLED(CMD_VIDCONSOLE) */
 736