file.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Helper functions used by the EFI stub on multiple
  4. * architectures. This should be #included by the EFI stub
  5. * implementation files.
  6. *
  7. * Copyright 2011 Intel Corporation; author Matt Fleming
  8. */
  9. #include <linux/efi.h>
  10. #include <asm/efi.h>
  11. #include "efistub.h"
  12. #define MAX_FILENAME_SIZE 256
  13. /*
  14. * Some firmware implementations have problems reading files in one go.
  15. * A read chunk size of 1MB seems to work for most platforms.
  16. *
  17. * Unfortunately, reading files in chunks triggers *other* bugs on some
  18. * platforms, so we provide a way to disable this workaround, which can
  19. * be done by passing "efi=nochunk" on the EFI boot stub command line.
  20. *
  21. * If you experience issues with initrd images being corrupt it's worth
  22. * trying efi=nochunk, but chunking is enabled by default on x86 because
  23. * there are far more machines that require the workaround than those that
  24. * break with it enabled.
  25. */
  26. #define EFI_READ_CHUNK_SIZE SZ_1M
  27. struct finfo {
  28. efi_file_info_t info;
  29. efi_char16_t filename[MAX_FILENAME_SIZE];
  30. };
  31. static efi_status_t efi_open_file(efi_file_protocol_t *volume,
  32. struct finfo *fi,
  33. efi_file_protocol_t **handle,
  34. unsigned long *file_size)
  35. {
  36. efi_guid_t info_guid = EFI_FILE_INFO_ID;
  37. efi_file_protocol_t *fh;
  38. unsigned long info_sz;
  39. efi_status_t status;
  40. status = volume->open(volume, &fh, fi->filename, EFI_FILE_MODE_READ, 0);
  41. if (status != EFI_SUCCESS) {
  42. efi_err("Failed to open file: %ls\n", fi->filename);
  43. return status;
  44. }
  45. info_sz = sizeof(struct finfo);
  46. status = fh->get_info(fh, &info_guid, &info_sz, fi);
  47. if (status != EFI_SUCCESS) {
  48. efi_err("Failed to get file info\n");
  49. fh->close(fh);
  50. return status;
  51. }
  52. *handle = fh;
  53. *file_size = fi->info.file_size;
  54. return EFI_SUCCESS;
  55. }
  56. static efi_status_t efi_open_volume(efi_loaded_image_t *image,
  57. efi_file_protocol_t **fh)
  58. {
  59. struct efi_vendor_dev_path *dp = image->file_path;
  60. efi_guid_t li_proto = LOADED_IMAGE_PROTOCOL_GUID;
  61. efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
  62. efi_simple_file_system_protocol_t *io;
  63. efi_status_t status;
  64. // If we are using EFI zboot, we should look for the file system
  65. // protocol on the parent image's handle instead
  66. if (IS_ENABLED(CONFIG_EFI_ZBOOT) &&
  67. image->parent_handle != NULL &&
  68. dp != NULL &&
  69. dp->header.type == EFI_DEV_MEDIA &&
  70. dp->header.sub_type == EFI_DEV_MEDIA_VENDOR &&
  71. !efi_guidcmp(dp->vendorguid, LINUX_EFI_ZBOOT_MEDIA_GUID)) {
  72. status = efi_bs_call(handle_protocol, image->parent_handle,
  73. &li_proto, (void *)&image);
  74. if (status != EFI_SUCCESS) {
  75. efi_err("Failed to locate parent image handle\n");
  76. return status;
  77. }
  78. }
  79. status = efi_bs_call(handle_protocol, image->device_handle, &fs_proto,
  80. (void **)&io);
  81. if (status != EFI_SUCCESS) {
  82. efi_err("Failed to handle fs_proto\n");
  83. return status;
  84. }
  85. status = io->open_volume(io, fh);
  86. if (status != EFI_SUCCESS)
  87. efi_err("Failed to open volume\n");
  88. return status;
  89. }
  90. static int find_file_option(const efi_char16_t *cmdline, int cmdline_len,
  91. const efi_char16_t *prefix, int prefix_size,
  92. efi_char16_t *result, int result_len)
  93. {
  94. int prefix_len = prefix_size / 2;
  95. bool found = false;
  96. int i;
  97. for (i = prefix_len; i < cmdline_len; i++) {
  98. if (!memcmp(&cmdline[i - prefix_len], prefix, prefix_size)) {
  99. found = true;
  100. break;
  101. }
  102. }
  103. if (!found)
  104. return 0;
  105. /* Skip any leading slashes */
  106. while (i < cmdline_len && (cmdline[i] == L'/' || cmdline[i] == L'\\'))
  107. i++;
  108. while (--result_len > 0 && i < cmdline_len) {
  109. efi_char16_t c = cmdline[i++];
  110. if (c == L'\0' || c == L'\n' || c == L' ')
  111. break;
  112. else if (c == L'/')
  113. /* Replace UNIX dir separators with EFI standard ones */
  114. *result++ = L'\\';
  115. else
  116. *result++ = c;
  117. }
  118. *result = L'\0';
  119. return i;
  120. }
  121. /*
  122. * Check the cmdline for a LILO-style file= arguments.
  123. *
  124. * We only support loading a file from the same filesystem as
  125. * the kernel image.
  126. */
  127. efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
  128. const efi_char16_t *optstr,
  129. int optstr_size,
  130. unsigned long soft_limit,
  131. unsigned long hard_limit,
  132. unsigned long *load_addr,
  133. unsigned long *load_size)
  134. {
  135. const efi_char16_t *cmdline = image->load_options;
  136. u32 cmdline_len = image->load_options_size;
  137. unsigned long efi_chunk_size = ULONG_MAX;
  138. efi_file_protocol_t *volume = NULL;
  139. efi_file_protocol_t *file;
  140. unsigned long alloc_addr;
  141. unsigned long alloc_size;
  142. efi_status_t status;
  143. int offset;
  144. if (!load_addr || !load_size)
  145. return EFI_INVALID_PARAMETER;
  146. efi_apply_loadoptions_quirk((const void **)&cmdline, &cmdline_len);
  147. cmdline_len /= sizeof(*cmdline);
  148. if (IS_ENABLED(CONFIG_X86) && !efi_nochunk)
  149. efi_chunk_size = EFI_READ_CHUNK_SIZE;
  150. alloc_addr = alloc_size = 0;
  151. do {
  152. struct finfo fi;
  153. unsigned long size;
  154. void *addr;
  155. offset = find_file_option(cmdline, cmdline_len,
  156. optstr, optstr_size,
  157. fi.filename, ARRAY_SIZE(fi.filename));
  158. if (!offset)
  159. break;
  160. cmdline += offset;
  161. cmdline_len -= offset;
  162. if (!volume) {
  163. status = efi_open_volume(image, &volume);
  164. if (status != EFI_SUCCESS)
  165. return status;
  166. }
  167. status = efi_open_file(volume, &fi, &file, &size);
  168. if (status != EFI_SUCCESS)
  169. goto err_close_volume;
  170. /*
  171. * Check whether the existing allocation can contain the next
  172. * file. This condition will also trigger naturally during the
  173. * first (and typically only) iteration of the loop, given that
  174. * alloc_size == 0 in that case.
  175. */
  176. if (round_up(alloc_size + size, EFI_ALLOC_ALIGN) >
  177. round_up(alloc_size, EFI_ALLOC_ALIGN)) {
  178. unsigned long old_addr = alloc_addr;
  179. status = EFI_OUT_OF_RESOURCES;
  180. if (soft_limit < hard_limit)
  181. status = efi_allocate_pages(alloc_size + size,
  182. &alloc_addr,
  183. soft_limit);
  184. if (status == EFI_OUT_OF_RESOURCES)
  185. status = efi_allocate_pages(alloc_size + size,
  186. &alloc_addr,
  187. hard_limit);
  188. if (status != EFI_SUCCESS) {
  189. efi_err("Failed to allocate memory for files\n");
  190. goto err_close_file;
  191. }
  192. if (old_addr != 0) {
  193. /*
  194. * This is not the first time we've gone
  195. * around this loop, and so we are loading
  196. * multiple files that need to be concatenated
  197. * and returned in a single buffer.
  198. */
  199. memcpy((void *)alloc_addr, (void *)old_addr, alloc_size);
  200. efi_free(alloc_size, old_addr);
  201. }
  202. }
  203. addr = (void *)alloc_addr + alloc_size;
  204. alloc_size += size;
  205. while (size) {
  206. unsigned long chunksize = min(size, efi_chunk_size);
  207. status = file->read(file, &chunksize, addr);
  208. if (status != EFI_SUCCESS) {
  209. efi_err("Failed to read file\n");
  210. goto err_close_file;
  211. }
  212. addr += chunksize;
  213. size -= chunksize;
  214. }
  215. file->close(file);
  216. } while (offset > 0);
  217. *load_addr = alloc_addr;
  218. *load_size = alloc_size;
  219. if (volume)
  220. volume->close(volume);
  221. if (*load_size == 0)
  222. return EFI_NOT_READY;
  223. return EFI_SUCCESS;
  224. err_close_file:
  225. file->close(file);
  226. err_close_volume:
  227. volume->close(volume);
  228. efi_free(alloc_size, alloc_addr);
  229. return status;
  230. }