init.c 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <fcntl.h>
  5. #include <sys/syscall.h>
  6. #include <sys/mount.h>
  7. #include <sys/reboot.h>
  8. #include <linux/kexec.h>
  9. /* from arch/x86/include/asm/setup.h */
  10. #define COMMAND_LINE_SIZE 2048
  11. #define KHO_FINALIZE "/debugfs/kho/out/finalize"
  12. #define KERNEL_IMAGE "/kernel"
  13. static int mount_filesystems(void)
  14. {
  15. if (mount("debugfs", "/debugfs", "debugfs", 0, NULL) < 0)
  16. return -1;
  17. return mount("proc", "/proc", "proc", 0, NULL);
  18. }
  19. static int kho_enable(void)
  20. {
  21. const char enable[] = "1";
  22. int fd;
  23. fd = open(KHO_FINALIZE, O_RDWR);
  24. if (fd < 0)
  25. return -1;
  26. if (write(fd, enable, sizeof(enable)) != sizeof(enable))
  27. return 1;
  28. close(fd);
  29. return 0;
  30. }
  31. static long kexec_file_load(int kernel_fd, int initrd_fd,
  32. unsigned long cmdline_len, const char *cmdline,
  33. unsigned long flags)
  34. {
  35. return syscall(__NR_kexec_file_load, kernel_fd, initrd_fd, cmdline_len,
  36. cmdline, flags);
  37. }
  38. static int kexec_load(void)
  39. {
  40. char cmdline[COMMAND_LINE_SIZE];
  41. ssize_t len;
  42. int fd, err;
  43. fd = open("/proc/cmdline", O_RDONLY);
  44. if (fd < 0)
  45. return -1;
  46. len = read(fd, cmdline, sizeof(cmdline));
  47. close(fd);
  48. if (len < 0)
  49. return -1;
  50. /* replace \n with \0 */
  51. cmdline[len - 1] = 0;
  52. fd = open(KERNEL_IMAGE, O_RDONLY);
  53. if (fd < 0)
  54. return -1;
  55. err = kexec_file_load(fd, -1, len, cmdline, KEXEC_FILE_NO_INITRAMFS);
  56. close(fd);
  57. return err ? : 0;
  58. }
  59. int main(int argc, char *argv[])
  60. {
  61. if (mount_filesystems())
  62. goto err_reboot;
  63. if (kho_enable())
  64. goto err_reboot;
  65. if (kexec_load())
  66. goto err_reboot;
  67. if (reboot(RB_KEXEC))
  68. goto err_reboot;
  69. return 0;
  70. err_reboot:
  71. reboot(RB_AUTOBOOT);
  72. return -1;
  73. }