stub.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #include <efi.h>
  2. #include <efilib.h>
  3. #include <elf.h>
  4. #include <dragonstub/dragonstub.h>
  5. extern void _image_end(void);
  6. static u64 image_base = 0;
  7. static u64 image_size = 0;
  8. static u64 image_end = 0;
  9. EFI_STATUS efi_handle_cmdline(EFI_LOADED_IMAGE *image, char **cmdline_ptr)
  10. {
  11. int cmdline_size = 0;
  12. EFI_STATUS status;
  13. char *cmdline;
  14. /*
  15. * Get the command line from EFI, using the LOADED_IMAGE
  16. * protocol. We are going to copy the command line into the
  17. * device tree, so this can be allocated anywhere.
  18. */
  19. cmdline = efi_convert_cmdline(image, &cmdline_size);
  20. if (!cmdline) {
  21. efi_err("getting command line via LOADED_IMAGE_PROTOCOL\n");
  22. return EFI_OUT_OF_RESOURCES;
  23. }
  24. // if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
  25. // IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
  26. // cmdline_size == 0) {
  27. // status = efi_parse_options(CONFIG_CMDLINE);
  28. // if (status != EFI_SUCCESS) {
  29. // efi_err("Failed to parse options\n");
  30. // goto fail_free_cmdline;
  31. // }
  32. // }
  33. // if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0) {
  34. if (cmdline_size > 0) {
  35. status = efi_parse_options(cmdline);
  36. if (status != EFI_SUCCESS) {
  37. efi_err("Failed to parse options\n");
  38. goto fail_free_cmdline;
  39. }
  40. }
  41. *cmdline_ptr = cmdline;
  42. return EFI_SUCCESS;
  43. fail_free_cmdline:
  44. efi_bs_call(FreePool, cmdline_ptr);
  45. return status;
  46. }
  47. static efi_status_t init_efi_program_info(efi_loaded_image_t *loaded_image)
  48. {
  49. image_base = (u64)loaded_image->ImageBase;
  50. image_size = loaded_image->ImageSize;
  51. image_end = (u64)_image_end;
  52. efi_info("DragonStub loaded at 0x%p\n", image_base);
  53. efi_info("DragonStub + payload size: 0x%p\n", image_size);
  54. efi_info("DragonStub end addr: 0x%p\n", image_end);
  55. return EFI_SUCCESS;
  56. }
  57. /// @brief payload_info的构造函数
  58. static struct payload_info payload_info_new(u64 payload_addr, u64 payload_size)
  59. {
  60. struct payload_info info = { .payload_addr = payload_addr,
  61. .payload_size = payload_size };
  62. return info;
  63. }
  64. static efi_status_t find_elf(struct payload_info *info)
  65. {
  66. extern __weak void _binary_payload_start(void);
  67. extern __weak void _binary_payload_end(void);
  68. extern __weak void _binary_payload_size(void);
  69. u64 payload_start = (u64)_binary_payload_start;
  70. u64 payload_end = (u64)_binary_payload_end;
  71. u64 payload_size = payload_end - payload_start;
  72. efi_info("payload_addr: %p\n", payload_start);
  73. efi_info("payload_end: %p\n", payload_end);
  74. efi_info("payload_size: %p\n", payload_size);
  75. if (payload_start == 0 || payload_end <= payload_start + 4 ||
  76. payload_size == 0) {
  77. return EFI_NOT_FOUND;
  78. }
  79. efi_debug("Checking payload's ELF header...\n");
  80. bool found = true;
  81. for (int i = 0; i < 4; i++) {
  82. u8 c = *(u8 *)(payload_start + i);
  83. if (c != ELFMAG[i]) {
  84. // 不是ELF magic number,跳过
  85. found = false;
  86. break;
  87. }
  88. }
  89. // 如果找到了ELF magic number,就认为找到了ELF header,稍后再验证
  90. if (found) {
  91. info->payload_addr = payload_start;
  92. info->payload_size = payload_size;
  93. return EFI_SUCCESS;
  94. }
  95. return EFI_NOT_FOUND;
  96. }
  97. /// @brief 寻找要加载的内核负载
  98. /// @param handle efi_handle
  99. /// @param image efi_loaded_image_t
  100. /// @param ret_info 返回的负载信息
  101. /// @return
  102. efi_status_t find_payload(efi_handle_t handle, efi_loaded_image_t *loaded_image,
  103. struct payload_info *ret_info)
  104. {
  105. efi_info("Try to find payload to boot\n");
  106. efi_status_t status = init_efi_program_info(loaded_image);
  107. if (status != EFI_SUCCESS) {
  108. efi_err("Failed to init efi program info\n");
  109. return status;
  110. }
  111. struct payload_info info = payload_info_new(0, 0);
  112. status = find_elf(&info);
  113. if (status != EFI_SUCCESS) {
  114. efi_err("Payload not found: Did you forget to add the payload by setting PAYLOAD_ELF at compile time?\n"
  115. "Or the payload is not an ELF file?\n");
  116. return status;
  117. }
  118. *ret_info = info;
  119. return EFI_SUCCESS;
  120. }