zboot.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/efi.h>
  3. #include <linux/pe.h>
  4. #include <asm/efi.h>
  5. #include <asm/unaligned.h>
  6. #include "efistub.h"
  7. static unsigned char zboot_heap[SZ_256K] __aligned(64);
  8. static unsigned long free_mem_ptr, free_mem_end_ptr;
  9. #define STATIC static
  10. #if defined(CONFIG_KERNEL_GZIP)
  11. #include "../../../../lib/decompress_inflate.c"
  12. #elif defined(CONFIG_KERNEL_LZ4)
  13. #include "../../../../lib/decompress_unlz4.c"
  14. #elif defined(CONFIG_KERNEL_LZMA)
  15. #include "../../../../lib/decompress_unlzma.c"
  16. #elif defined(CONFIG_KERNEL_LZO)
  17. #include "../../../../lib/decompress_unlzo.c"
  18. #elif defined(CONFIG_KERNEL_XZ)
  19. #undef memcpy
  20. #define memcpy memcpy
  21. #undef memmove
  22. #define memmove memmove
  23. #include "../../../../lib/decompress_unxz.c"
  24. #elif defined(CONFIG_KERNEL_ZSTD)
  25. #include "../../../../lib/decompress_unzstd.c"
  26. #endif
  27. extern char efi_zboot_header[];
  28. extern char _gzdata_start[], _gzdata_end[];
  29. static void log(efi_char16_t str[])
  30. {
  31. efi_call_proto(efi_table_attr(efi_system_table, con_out),
  32. output_string, L"EFI decompressor: ");
  33. efi_call_proto(efi_table_attr(efi_system_table, con_out),
  34. output_string, str);
  35. efi_call_proto(efi_table_attr(efi_system_table, con_out),
  36. output_string, L"\n");
  37. }
  38. static void error(char *x)
  39. {
  40. log(L"error() called from decompressor library\n");
  41. }
  42. // Local version to avoid pulling in memcmp()
  43. static bool guids_eq(const efi_guid_t *a, const efi_guid_t *b)
  44. {
  45. const u32 *l = (u32 *)a;
  46. const u32 *r = (u32 *)b;
  47. return l[0] == r[0] && l[1] == r[1] && l[2] == r[2] && l[3] == r[3];
  48. }
  49. static efi_status_t __efiapi
  50. load_file(efi_load_file_protocol_t *this, efi_device_path_protocol_t *rem,
  51. bool boot_policy, unsigned long *bufsize, void *buffer)
  52. {
  53. unsigned long compressed_size = _gzdata_end - _gzdata_start;
  54. struct efi_vendor_dev_path *vendor_dp;
  55. bool decompress = false;
  56. unsigned long size;
  57. int ret;
  58. if (rem == NULL || bufsize == NULL)
  59. return EFI_INVALID_PARAMETER;
  60. if (boot_policy)
  61. return EFI_UNSUPPORTED;
  62. // Look for our vendor media device node in the remaining file path
  63. if (rem->type == EFI_DEV_MEDIA &&
  64. rem->sub_type == EFI_DEV_MEDIA_VENDOR) {
  65. vendor_dp = container_of(rem, struct efi_vendor_dev_path, header);
  66. if (!guids_eq(&vendor_dp->vendorguid, &LINUX_EFI_ZBOOT_MEDIA_GUID))
  67. return EFI_NOT_FOUND;
  68. decompress = true;
  69. rem = (void *)(vendor_dp + 1);
  70. }
  71. if (rem->type != EFI_DEV_END_PATH ||
  72. rem->sub_type != EFI_DEV_END_ENTIRE)
  73. return EFI_NOT_FOUND;
  74. // The uncompressed size of the payload is appended to the raw bit
  75. // stream, and may therefore appear misaligned in memory
  76. size = decompress ? get_unaligned_le32(_gzdata_end - 4)
  77. : compressed_size;
  78. if (buffer == NULL || *bufsize < size) {
  79. *bufsize = size;
  80. return EFI_BUFFER_TOO_SMALL;
  81. }
  82. if (decompress) {
  83. ret = __decompress(_gzdata_start, compressed_size, NULL, NULL,
  84. buffer, size, NULL, error);
  85. if (ret < 0) {
  86. log(L"Decompression failed");
  87. return EFI_DEVICE_ERROR;
  88. }
  89. } else {
  90. memcpy(buffer, _gzdata_start, compressed_size);
  91. }
  92. return EFI_SUCCESS;
  93. }
  94. // Return the length in bytes of the device path up to the first end node.
  95. static int device_path_length(const efi_device_path_protocol_t *dp)
  96. {
  97. int len = 0;
  98. while (dp->type != EFI_DEV_END_PATH) {
  99. len += dp->length;
  100. dp = (void *)((u8 *)dp + dp->length);
  101. }
  102. return len;
  103. }
  104. static void append_rel_offset_node(efi_device_path_protocol_t **dp,
  105. unsigned long start, unsigned long end)
  106. {
  107. struct efi_rel_offset_dev_path *rodp = (void *)*dp;
  108. rodp->header.type = EFI_DEV_MEDIA;
  109. rodp->header.sub_type = EFI_DEV_MEDIA_REL_OFFSET;
  110. rodp->header.length = sizeof(struct efi_rel_offset_dev_path);
  111. rodp->reserved = 0;
  112. rodp->starting_offset = start;
  113. rodp->ending_offset = end;
  114. *dp = (void *)(rodp + 1);
  115. }
  116. static void append_ven_media_node(efi_device_path_protocol_t **dp,
  117. efi_guid_t *guid)
  118. {
  119. struct efi_vendor_dev_path *vmdp = (void *)*dp;
  120. vmdp->header.type = EFI_DEV_MEDIA;
  121. vmdp->header.sub_type = EFI_DEV_MEDIA_VENDOR;
  122. vmdp->header.length = sizeof(struct efi_vendor_dev_path);
  123. vmdp->vendorguid = *guid;
  124. *dp = (void *)(vmdp + 1);
  125. }
  126. static void append_end_node(efi_device_path_protocol_t **dp)
  127. {
  128. (*dp)->type = EFI_DEV_END_PATH;
  129. (*dp)->sub_type = EFI_DEV_END_ENTIRE;
  130. (*dp)->length = sizeof(struct efi_generic_dev_path);
  131. ++*dp;
  132. }
  133. asmlinkage efi_status_t __efiapi
  134. efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
  135. {
  136. struct efi_mem_mapped_dev_path mmdp = {
  137. .header.type = EFI_DEV_HW,
  138. .header.sub_type = EFI_DEV_MEM_MAPPED,
  139. .header.length = sizeof(struct efi_mem_mapped_dev_path)
  140. };
  141. efi_device_path_protocol_t *parent_dp, *dpp, *lf2_dp, *li_dp;
  142. efi_load_file2_protocol_t zboot_load_file2;
  143. efi_loaded_image_t *parent, *child;
  144. unsigned long exit_data_size;
  145. efi_handle_t child_handle;
  146. efi_handle_t zboot_handle;
  147. efi_char16_t *exit_data;
  148. efi_status_t status;
  149. void *dp_alloc;
  150. int dp_len;
  151. WRITE_ONCE(efi_system_table, systab);
  152. free_mem_ptr = (unsigned long)&zboot_heap;
  153. free_mem_end_ptr = free_mem_ptr + sizeof(zboot_heap);
  154. exit_data = NULL;
  155. exit_data_size = 0;
  156. status = efi_bs_call(handle_protocol, handle,
  157. &LOADED_IMAGE_PROTOCOL_GUID, (void **)&parent);
  158. if (status != EFI_SUCCESS) {
  159. log(L"Failed to locate parent's loaded image protocol");
  160. return status;
  161. }
  162. status = efi_bs_call(handle_protocol, handle,
  163. &LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID,
  164. (void **)&parent_dp);
  165. if (status != EFI_SUCCESS || parent_dp == NULL) {
  166. // Create a MemoryMapped() device path node to describe
  167. // the parent image if no device path was provided.
  168. mmdp.memory_type = parent->image_code_type;
  169. mmdp.starting_addr = (unsigned long)parent->image_base;
  170. mmdp.ending_addr = (unsigned long)parent->image_base +
  171. parent->image_size - 1;
  172. parent_dp = &mmdp.header;
  173. dp_len = sizeof(mmdp);
  174. } else {
  175. dp_len = device_path_length(parent_dp);
  176. }
  177. // Allocate some pool memory for device path protocol data
  178. status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
  179. 2 * (dp_len + sizeof(struct efi_rel_offset_dev_path) +
  180. sizeof(struct efi_generic_dev_path)) +
  181. sizeof(struct efi_vendor_dev_path),
  182. (void **)&dp_alloc);
  183. if (status != EFI_SUCCESS) {
  184. log(L"Failed to allocate device path pool memory");
  185. return status;
  186. }
  187. // Create a device path describing the compressed payload in this image
  188. // <...parent_dp...>/Offset(<start>, <end>)
  189. lf2_dp = memcpy(dp_alloc, parent_dp, dp_len);
  190. dpp = (void *)((u8 *)lf2_dp + dp_len);
  191. append_rel_offset_node(&dpp,
  192. (unsigned long)(_gzdata_start - efi_zboot_header),
  193. (unsigned long)(_gzdata_end - efi_zboot_header - 1));
  194. append_end_node(&dpp);
  195. // Create a device path describing the decompressed payload in this image
  196. // <...parent_dp...>/Offset(<start>, <end>)/VenMedia(ZBOOT_MEDIA_GUID)
  197. dp_len += sizeof(struct efi_rel_offset_dev_path);
  198. li_dp = memcpy(dpp, lf2_dp, dp_len);
  199. dpp = (void *)((u8 *)li_dp + dp_len);
  200. append_ven_media_node(&dpp, &LINUX_EFI_ZBOOT_MEDIA_GUID);
  201. append_end_node(&dpp);
  202. zboot_handle = NULL;
  203. zboot_load_file2.load_file = load_file;
  204. status = efi_bs_call(install_multiple_protocol_interfaces,
  205. &zboot_handle,
  206. &EFI_DEVICE_PATH_PROTOCOL_GUID, lf2_dp,
  207. &EFI_LOAD_FILE2_PROTOCOL_GUID, &zboot_load_file2,
  208. NULL);
  209. if (status != EFI_SUCCESS) {
  210. log(L"Failed to install LoadFile2 protocol and device path");
  211. goto free_dpalloc;
  212. }
  213. status = efi_bs_call(load_image, false, handle, li_dp, NULL, 0,
  214. &child_handle);
  215. if (status != EFI_SUCCESS) {
  216. log(L"Failed to load image");
  217. goto uninstall_lf2;
  218. }
  219. status = efi_bs_call(handle_protocol, child_handle,
  220. &LOADED_IMAGE_PROTOCOL_GUID, (void **)&child);
  221. if (status != EFI_SUCCESS) {
  222. log(L"Failed to locate child's loaded image protocol");
  223. goto unload_image;
  224. }
  225. // Copy the kernel command line
  226. child->load_options = parent->load_options;
  227. child->load_options_size = parent->load_options_size;
  228. status = efi_bs_call(start_image, child_handle, &exit_data_size,
  229. &exit_data);
  230. if (status != EFI_SUCCESS) {
  231. log(L"StartImage() returned with error");
  232. if (exit_data_size > 0)
  233. log(exit_data);
  234. // If StartImage() returns EFI_SECURITY_VIOLATION, the image is
  235. // not unloaded so we need to do it by hand.
  236. if (status == EFI_SECURITY_VIOLATION)
  237. unload_image:
  238. efi_bs_call(unload_image, child_handle);
  239. }
  240. uninstall_lf2:
  241. efi_bs_call(uninstall_multiple_protocol_interfaces,
  242. zboot_handle,
  243. &EFI_DEVICE_PATH_PROTOCOL_GUID, lf2_dp,
  244. &EFI_LOAD_FILE2_PROTOCOL_GUID, &zboot_load_file2,
  245. NULL);
  246. free_dpalloc:
  247. efi_bs_call(free_pool, dp_alloc);
  248. efi_bs_call(exit, handle, status, exit_data_size, exit_data);
  249. // Free ExitData in case Exit() returned with a failure code,
  250. // but return the original status code.
  251. log(L"Exit() returned with failure code");
  252. if (exit_data != NULL)
  253. efi_bs_call(free_pool, exit_data);
  254. return status;
  255. }