efitextmode.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2022 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. * Set/Get UEFI text output mode resolution.
  19. */
  20. #include <grub/dl.h>
  21. #include <grub/misc.h>
  22. #include <grub/mm.h>
  23. #include <grub/command.h>
  24. #include <grub/i18n.h>
  25. #include <grub/efi/efi.h>
  26. #include <grub/efi/api.h>
  27. GRUB_MOD_LICENSE ("GPLv3+");
  28. static grub_err_t
  29. grub_efi_set_mode (grub_efi_simple_text_output_interface_t *o,
  30. grub_efi_int32_t mode)
  31. {
  32. grub_efi_status_t status;
  33. if (mode != o->mode->mode)
  34. {
  35. status = o->set_mode (o, mode);
  36. if (status == GRUB_EFI_SUCCESS)
  37. ;
  38. else if (status == GRUB_EFI_DEVICE_ERROR)
  39. return grub_error (GRUB_ERR_BAD_DEVICE,
  40. N_("device error: could not set requested mode"));
  41. else if (status == GRUB_EFI_UNSUPPORTED)
  42. return grub_error (GRUB_ERR_OUT_OF_RANGE,
  43. N_("invalid mode: number not valid"));
  44. else
  45. return grub_error (GRUB_ERR_BAD_FIRMWARE,
  46. N_("unexpected EFI error number: `%u'"),
  47. (unsigned) status);
  48. }
  49. return GRUB_ERR_NONE;
  50. }
  51. static grub_err_t
  52. grub_cmd_efitextmode (grub_command_t cmd __attribute__ ((unused)),
  53. int argc, char **args)
  54. {
  55. grub_efi_simple_text_output_interface_t *o = grub_efi_system_table->con_out;
  56. unsigned long mode;
  57. const char *p = NULL;
  58. grub_err_t err;
  59. grub_efi_uintn_t columns, rows;
  60. grub_efi_int32_t i;
  61. if (o == NULL)
  62. return grub_error (GRUB_ERR_BAD_DEVICE, N_("no UEFI output console interface"));
  63. if (o->mode == NULL)
  64. return grub_error (GRUB_ERR_BUG, N_("no mode struct for UEFI output console"));
  65. if (argc > 2)
  66. return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("at most two arguments expected"));
  67. if (argc == 0)
  68. {
  69. grub_printf_ (N_("Available modes for console output device.\n"));
  70. for (i = 0; i < o->mode->max_mode; i++)
  71. if (GRUB_EFI_SUCCESS == o->query_mode (o, i, &columns, &rows))
  72. grub_printf_ (N_(" [%" PRIuGRUB_EFI_UINT32_T "] Col %5"
  73. PRIuGRUB_EFI_UINTN_T " Row %5" PRIuGRUB_EFI_UINTN_T
  74. " %c\n"),
  75. i, columns, rows, (i == o->mode->mode) ? '*' : ' ');
  76. }
  77. else if (argc == 1)
  78. {
  79. if (grub_strcmp (args[0], "min") == 0)
  80. mode = 0;
  81. else if (grub_strcmp (args[0], "max") == 0)
  82. mode = o->mode->max_mode - 1;
  83. else
  84. {
  85. mode = grub_strtoul (args[0], &p, 0);
  86. if (*args[0] == '\0' || *p != '\0')
  87. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  88. N_("non-numeric or invalid mode `%s'"), args[0]);
  89. }
  90. if (mode < (unsigned long) o->mode->max_mode)
  91. {
  92. err = grub_efi_set_mode (o, (grub_efi_int32_t) mode);
  93. if (err != GRUB_ERR_NONE)
  94. return err;
  95. }
  96. else
  97. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  98. N_("invalid mode: `%lu' is greater than maximum mode `%lu'"),
  99. mode, (unsigned long) o->mode->max_mode);
  100. }
  101. else if (argc == 2)
  102. {
  103. grub_efi_uintn_t u_columns, u_rows;
  104. u_columns = (grub_efi_uintn_t) grub_strtoul (args[0], &p, 0);
  105. if (*args[0] == '\0' || *p != '\0')
  106. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  107. N_("non-numeric or invalid columns number `%s'"), args[0]);
  108. u_rows = (grub_efi_uintn_t) grub_strtoul (args[1], &p, 0);
  109. if (*args[1] == '\0' || *p != '\0')
  110. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  111. N_("non-numeric or invalid rows number `%s'"), args[1]);
  112. for (i = 0; i < o->mode->max_mode; i++)
  113. if (GRUB_EFI_SUCCESS == o->query_mode (o, i, &columns, &rows))
  114. if (u_columns == columns && u_rows == rows)
  115. return grub_efi_set_mode (o, (grub_efi_int32_t) i);
  116. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  117. N_("no mode found with requested columns and rows"));
  118. }
  119. return GRUB_ERR_NONE;
  120. }
  121. static grub_command_t cmd;
  122. GRUB_MOD_INIT (efitextmode)
  123. {
  124. cmd = grub_register_command ("efitextmode", grub_cmd_efitextmode,
  125. N_("[min | max | <mode_num> | <cols> <rows>]"),
  126. N_("Get or set EFI text mode."));
  127. }
  128. GRUB_MOD_FINI (efitextmode)
  129. {
  130. grub_unregister_command (cmd);
  131. }