serial_efi.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2015 Google, Inc
  4. * Written by Simon Glass <sjg@chromium.org>
  5. */
  6. #include <common.h>
  7. #include <debug_uart.h>
  8. #include <dm.h>
  9. #include <efi.h>
  10. #include <efi_api.h>
  11. #include <errno.h>
  12. #include <fdtdec.h>
  13. #include <log.h>
  14. #include <linux/compiler.h>
  15. #include <asm/io.h>
  16. #include <serial.h>
  17. /* Information about the efi console */
  18. struct serial_efi_priv {
  19. struct efi_simple_text_input_protocol *con_in;
  20. struct efi_simple_text_output_protocol *con_out;
  21. struct efi_input_key key;
  22. bool have_key;
  23. };
  24. int serial_efi_setbrg(struct udevice *dev, int baudrate)
  25. {
  26. return 0;
  27. }
  28. static int serial_efi_get_key(struct serial_efi_priv *priv)
  29. {
  30. int ret;
  31. if (priv->have_key)
  32. return 0;
  33. ret = priv->con_in->read_key_stroke(priv->con_in, &priv->key);
  34. if (ret == EFI_NOT_READY)
  35. return -EAGAIN;
  36. else if (ret != EFI_SUCCESS)
  37. return -EIO;
  38. priv->have_key = true;
  39. return 0;
  40. }
  41. static int serial_efi_getc(struct udevice *dev)
  42. {
  43. struct serial_efi_priv *priv = dev_get_priv(dev);
  44. int ret, ch;
  45. ret = serial_efi_get_key(priv);
  46. if (ret)
  47. return ret;
  48. priv->have_key = false;
  49. ch = priv->key.unicode_char;
  50. /*
  51. * Unicode char 8 (for backspace) is never returned. Instead we get a
  52. * key scan code of 8. Handle this so that backspace works correctly
  53. * in the U-Boot command line.
  54. */
  55. if (!ch && priv->key.scan_code == 8)
  56. ch = 8;
  57. debug(" [%x %x %x] ", ch, priv->key.unicode_char, priv->key.scan_code);
  58. return ch;
  59. }
  60. static int serial_efi_putc(struct udevice *dev, const char ch)
  61. {
  62. struct serial_efi_priv *priv = dev_get_priv(dev);
  63. uint16_t ucode[2];
  64. int ret;
  65. ucode[0] = ch;
  66. ucode[1] = '\0';
  67. ret = priv->con_out->output_string(priv->con_out, ucode);
  68. if (ret)
  69. return -EIO;
  70. return 0;
  71. }
  72. static int serial_efi_pending(struct udevice *dev, bool input)
  73. {
  74. struct serial_efi_priv *priv = dev_get_priv(dev);
  75. int ret;
  76. /* We assume that EFI will stall if its output buffer fills up */
  77. if (!input)
  78. return 0;
  79. ret = serial_efi_get_key(priv);
  80. if (ret == -EAGAIN)
  81. return 0;
  82. else if (ret)
  83. return ret;
  84. return 1;
  85. }
  86. /*
  87. * There is nothing to init here since the EFI console is already running by
  88. * the time we enter U-Boot.
  89. */
  90. static inline void _debug_uart_init(void)
  91. {
  92. }
  93. static inline void _debug_uart_putc(int ch)
  94. {
  95. struct efi_system_table *sys_table = efi_get_sys_table();
  96. uint16_t ucode[2];
  97. ucode[0] = ch;
  98. ucode[1] = '\0';
  99. sys_table->con_out->output_string(sys_table->con_out, ucode);
  100. }
  101. DEBUG_UART_FUNCS
  102. static int serial_efi_probe(struct udevice *dev)
  103. {
  104. struct efi_system_table *table = efi_get_sys_table();
  105. struct serial_efi_priv *priv = dev_get_priv(dev);
  106. priv->con_in = table->con_in;
  107. priv->con_out = table->con_out;
  108. return 0;
  109. }
  110. static const struct dm_serial_ops serial_efi_ops = {
  111. .putc = serial_efi_putc,
  112. .getc = serial_efi_getc,
  113. .pending = serial_efi_pending,
  114. .setbrg = serial_efi_setbrg,
  115. };
  116. static const struct udevice_id serial_efi_ids[] = {
  117. { .compatible = "efi,uart" },
  118. { }
  119. };
  120. U_BOOT_DRIVER(serial_efi) = {
  121. .name = "serial_efi",
  122. .id = UCLASS_SERIAL,
  123. .of_match = serial_efi_ids,
  124. .priv_auto = sizeof(struct serial_efi_priv),
  125. .probe = serial_efi_probe,
  126. .ops = &serial_efi_ops,
  127. };