tuxonice_ui.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * kernel/power/tuxonice_ui.c
  3. *
  4. * Copyright (C) 1998-2001 Gabor Kuti <seasons@fornax.hu>
  5. * Copyright (C) 1998,2001,2002 Pavel Machek <pavel@suse.cz>
  6. * Copyright (C) 2002-2003 Florent Chabaud <fchabaud@free.fr>
  7. * Copyright (C) 2002-2014 Nigel Cunningham (nigel at tuxonice net)
  8. *
  9. * This file is released under the GPLv2.
  10. *
  11. * Routines for TuxOnIce's user interface.
  12. *
  13. * The user interface code talks to a userspace program via a
  14. * netlink socket.
  15. *
  16. * The kernel side:
  17. * - starts the userui program;
  18. * - sends text messages and progress bar status;
  19. *
  20. * The user space side:
  21. * - passes messages regarding user requests (abort, toggle reboot etc)
  22. *
  23. */
  24. #define __KERNEL_SYSCALLS__
  25. #include <linux/reboot.h>
  26. #include "tuxonice_sysfs.h"
  27. #include "tuxonice_modules.h"
  28. #include "tuxonice.h"
  29. #include "tuxonice_ui.h"
  30. #include "tuxonice_netlink.h"
  31. #include "tuxonice_power_off.h"
  32. #include "tuxonice_builtin.h"
  33. static char local_printf_buf[1024]; /* Same as printk - should be safe */
  34. struct ui_ops *toi_current_ui;
  35. EXPORT_SYMBOL_GPL(toi_current_ui);
  36. /**
  37. * toi_wait_for_keypress - Wait for keypress via userui or /dev/console.
  38. *
  39. * @timeout: Maximum time to wait.
  40. *
  41. * Wait for a keypress, either from userui or /dev/console if userui isn't
  42. * available. The non-userui path is particularly for at boot-time, prior
  43. * to userui being started, when we have an important warning to give to
  44. * the user.
  45. */
  46. #if defined(CONFIG_VT) || defined(CONFIG_SERIAL_CONSOLE)
  47. static char toi_wait_for_keypress(int timeout)
  48. {
  49. if (toi_current_ui && toi_current_ui->wait_for_key(timeout))
  50. return ' ';
  51. return toi_wait_for_keypress_dev_console(timeout);
  52. }
  53. #endif
  54. /* toi_early_boot_message()
  55. * Description: Handle errors early in the process of booting.
  56. * The user may press C to continue booting, perhaps
  57. * invalidating the image, or space to reboot.
  58. * This works from either the serial console or normally
  59. * attached keyboard.
  60. *
  61. * Note that we come in here from init, while the kernel is
  62. * locked. If we want to get events from the serial console,
  63. * we need to temporarily unlock the kernel.
  64. *
  65. * toi_early_boot_message may also be called post-boot.
  66. * In this case, it simply printks the message and returns.
  67. *
  68. * Arguments: int Whether we are able to erase the image.
  69. * int default_answer. What to do when we timeout. This
  70. * will normally be continue, but the user might
  71. * provide command line options (__setup) to override
  72. * particular cases.
  73. * Char *. Pointer to a string explaining why we're moaning.
  74. */
  75. #define say(message, a...) pr_err(message, ##a)
  76. void toi_early_boot_message(int message_detail, int default_answer, char *warning_reason, ...)
  77. {
  78. unsigned long orig_state = get_toi_state(), continue_req = 0;
  79. #if defined(CONFIG_VT) || defined(CONFIG_SERIAL_CONSOLE)
  80. unsigned long orig_loglevel = console_loglevel;
  81. int can_ask = 1;
  82. #else
  83. int can_ask = 0;
  84. #endif
  85. va_list args;
  86. int printed_len;
  87. if (!toi_wait) {
  88. set_toi_state(TOI_CONTINUE_REQ);
  89. can_ask = 0;
  90. }
  91. if (warning_reason) {
  92. va_start(args, warning_reason);
  93. printed_len = vsnprintf(local_printf_buf,
  94. sizeof(local_printf_buf), warning_reason, args);
  95. va_end(args);
  96. }
  97. if (!test_toi_state(TOI_BOOT_TIME)) {
  98. pr_warn("TuxOnIce: %s\n", local_printf_buf);
  99. return;
  100. }
  101. if (!can_ask) {
  102. continue_req = !!default_answer;
  103. goto post_ask;
  104. }
  105. #if defined(CONFIG_VT) || defined(CONFIG_SERIAL_CONSOLE)
  106. console_loglevel = 7;
  107. say("=== TuxOnIce ===");
  108. if (warning_reason) {
  109. say("BIG FAT WARNING!! %s", local_printf_buf);
  110. switch (message_detail) {
  111. case 0:
  112. say("If you continue booting, note that any image WILL NOT BE REMOVED")
  113. /* TuxOnIce is unable to do so because the appropriate modules aren't loaded.
  114. * You should manually remove the image to avoid any possibility of corrupting
  115. * your filesystem(s) later.
  116. */
  117. break;
  118. case 1:
  119. say("If you want to use current TuxOnIce image, reboot again with the same kernel");
  120. /* If you want to forget that image, continue and the image will be erased. */
  121. break;
  122. }
  123. say("Press SPACE to reboot or C to continue booting with " "this kernel\n");
  124. if (toi_wait > 0)
  125. say("Default action if you don't select one in %d seconds is: %s.\n",
  126. toi_wait,
  127. default_answer == TOI_CONTINUE_REQ ? "continue booting" : "reboot");
  128. } else {
  129. say("BIG FAT WARNING!!");
  130. /* You have tried to resume from this image before.
  131. * If it failed once, it may well fail again.
  132. * Would you like to remove the image and boot normally?
  133. * This will be equivalent to entering noresume on the kernel command line.
  134. */
  135. say("Press SPACE to remove the image or C to continue " "resuming.\n\n");
  136. if (toi_wait > 0)
  137. say("Default action if you don't select one in %d seconds is: %s.\n", toi_wait,
  138. !!default_answer ? "continue resuming" : "remove the image");
  139. }
  140. console_loglevel = orig_loglevel;
  141. set_toi_state(TOI_SANITY_CHECK_PROMPT);
  142. clear_toi_state(TOI_CONTINUE_REQ);
  143. if (toi_wait_for_keypress(toi_wait) == 0) /* We timed out */
  144. continue_req = !!default_answer;
  145. else
  146. continue_req = test_toi_state(TOI_CONTINUE_REQ);
  147. #endif /* CONFIG_VT or CONFIG_SERIAL_CONSOLE */
  148. post_ask:
  149. if ((warning_reason) && (!continue_req))
  150. kernel_restart(NULL);
  151. restore_toi_state(orig_state);
  152. if (continue_req)
  153. set_toi_state(TOI_CONTINUE_REQ);
  154. }
  155. EXPORT_SYMBOL_GPL(toi_early_boot_message);
  156. #undef say
  157. /*
  158. * User interface specific /sys/power/tuxonice entries.
  159. */
  160. static struct toi_sysfs_data sysfs_params[] = {
  161. #if defined(CONFIG_NET) && defined(CONFIG_SYSFS)
  162. SYSFS_INT("default_console_level", SYSFS_RW,
  163. &toi_bkd.toi_default_console_level, 0, 7, 0, NULL),
  164. SYSFS_UL("debug_sections", SYSFS_RW, &toi_bkd.toi_debug_state, 0,
  165. 1 << 30, 0),
  166. SYSFS_BIT("log_everything", SYSFS_RW, &toi_bkd.toi_action, TOI_LOGALL,
  167. 0)
  168. #endif
  169. };
  170. static struct toi_module_ops userui_ops = {
  171. .type = MISC_HIDDEN_MODULE,
  172. .name = "printk ui",
  173. .directory = "user_interface",
  174. .module = THIS_MODULE,
  175. .sysfs_data = sysfs_params,
  176. .num_sysfs_entries = sizeof(sysfs_params) / sizeof(struct toi_sysfs_data),
  177. };
  178. int toi_register_ui_ops(struct ui_ops *this_ui)
  179. {
  180. if (toi_current_ui) {
  181. pr_warn("Only one TuxOnIce user interface module can be loaded at a time.");
  182. return -EBUSY;
  183. }
  184. toi_current_ui = this_ui;
  185. return 0;
  186. }
  187. EXPORT_SYMBOL_GPL(toi_register_ui_ops);
  188. void toi_remove_ui_ops(struct ui_ops *this_ui)
  189. {
  190. if (toi_current_ui != this_ui)
  191. return;
  192. toi_current_ui = NULL;
  193. }
  194. EXPORT_SYMBOL_GPL(toi_remove_ui_ops);
  195. /* toi_console_sysfs_init
  196. * Description: Boot time initialisation for user interface.
  197. */
  198. int toi_ui_init(void)
  199. {
  200. return toi_register_module(&userui_ops);
  201. }
  202. void toi_ui_exit(void)
  203. {
  204. toi_unregister_module(&userui_ops);
  205. }