mkeficapsule.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright 2018 Linaro Limited
  4. * Author: AKASHI Takahiro
  5. */
  6. #include <getopt.h>
  7. #include <malloc.h>
  8. #include <stdbool.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <linux/types.h>
  13. #include <sys/stat.h>
  14. #include <sys/types.h>
  15. typedef __u8 u8;
  16. typedef __u16 u16;
  17. typedef __u32 u32;
  18. typedef __u64 u64;
  19. typedef __s16 s16;
  20. typedef __s32 s32;
  21. #define aligned_u64 __aligned_u64
  22. #ifndef __packed
  23. #define __packed __attribute__((packed))
  24. #endif
  25. #include <efi.h>
  26. #include <efi_api.h>
  27. static const char *tool_name = "mkeficapsule";
  28. efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
  29. efi_guid_t efi_guid_image_type_uboot_fit =
  30. EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID;
  31. efi_guid_t efi_guid_image_type_uboot_raw =
  32. EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID;
  33. static struct option options[] = {
  34. {"fit", required_argument, NULL, 'f'},
  35. {"raw", required_argument, NULL, 'r'},
  36. {"index", required_argument, NULL, 'i'},
  37. {"instance", required_argument, NULL, 'I'},
  38. {"help", no_argument, NULL, 'h'},
  39. {NULL, 0, NULL, 0},
  40. };
  41. static void print_usage(void)
  42. {
  43. printf("Usage: %s [options] <output file>\n"
  44. "Options:\n"
  45. "\t-f, --fit <fit image> new FIT image file\n"
  46. "\t-r, --raw <raw image> new raw image file\n"
  47. "\t-i, --index <index> update image index\n"
  48. "\t-I, --instance <instance> update hardware instance\n"
  49. "\t-h, --help print a help message\n",
  50. tool_name);
  51. }
  52. static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
  53. unsigned long index, unsigned long instance)
  54. {
  55. struct efi_capsule_header header;
  56. struct efi_firmware_management_capsule_header capsule;
  57. struct efi_firmware_management_capsule_image_header image;
  58. FILE *f, *g;
  59. struct stat bin_stat;
  60. u8 *data;
  61. size_t size;
  62. u64 offset;
  63. #ifdef DEBUG
  64. printf("For output: %s\n", path);
  65. printf("\tbin: %s\n\ttype: %pUl\n", bin, guid);
  66. printf("\tindex: %ld\n\tinstance: %ld\n", index, instance);
  67. #endif
  68. g = fopen(bin, "r");
  69. if (!g) {
  70. printf("cannot open %s\n", bin);
  71. return -1;
  72. }
  73. if (stat(bin, &bin_stat) < 0) {
  74. printf("cannot determine the size of %s\n", bin);
  75. goto err_1;
  76. }
  77. data = malloc(bin_stat.st_size);
  78. if (!data) {
  79. printf("cannot allocate memory: %zx\n", (size_t)bin_stat.st_size);
  80. goto err_1;
  81. }
  82. f = fopen(path, "w");
  83. if (!f) {
  84. printf("cannot open %s\n", path);
  85. goto err_2;
  86. }
  87. header.capsule_guid = efi_guid_fm_capsule;
  88. header.header_size = sizeof(header);
  89. /* TODO: The current implementation ignores flags */
  90. header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
  91. header.capsule_image_size = sizeof(header)
  92. + sizeof(capsule) + sizeof(u64)
  93. + sizeof(image)
  94. + bin_stat.st_size;
  95. size = fwrite(&header, 1, sizeof(header), f);
  96. if (size < sizeof(header)) {
  97. printf("write failed (%zx)\n", size);
  98. goto err_3;
  99. }
  100. capsule.version = 0x00000001;
  101. capsule.embedded_driver_count = 0;
  102. capsule.payload_item_count = 1;
  103. size = fwrite(&capsule, 1, sizeof(capsule), f);
  104. if (size < (sizeof(capsule))) {
  105. printf("write failed (%zx)\n", size);
  106. goto err_3;
  107. }
  108. offset = sizeof(capsule) + sizeof(u64);
  109. size = fwrite(&offset, 1, sizeof(offset), f);
  110. if (size < sizeof(offset)) {
  111. printf("write failed (%zx)\n", size);
  112. goto err_3;
  113. }
  114. image.version = 0x00000003;
  115. memcpy(&image.update_image_type_id, guid, sizeof(*guid));
  116. image.update_image_index = index;
  117. image.reserved[0] = 0;
  118. image.reserved[1] = 0;
  119. image.reserved[2] = 0;
  120. image.update_image_size = bin_stat.st_size;
  121. image.update_vendor_code_size = 0; /* none */
  122. image.update_hardware_instance = instance;
  123. image.image_capsule_support = 0;
  124. size = fwrite(&image, 1, sizeof(image), f);
  125. if (size < sizeof(image)) {
  126. printf("write failed (%zx)\n", size);
  127. goto err_3;
  128. }
  129. size = fread(data, 1, bin_stat.st_size, g);
  130. if (size < bin_stat.st_size) {
  131. printf("read failed (%zx)\n", size);
  132. goto err_3;
  133. }
  134. size = fwrite(data, 1, bin_stat.st_size, f);
  135. if (size < bin_stat.st_size) {
  136. printf("write failed (%zx)\n", size);
  137. goto err_3;
  138. }
  139. fclose(f);
  140. fclose(g);
  141. free(data);
  142. return 0;
  143. err_3:
  144. fclose(f);
  145. err_2:
  146. free(data);
  147. err_1:
  148. fclose(g);
  149. return -1;
  150. }
  151. /*
  152. * Usage:
  153. * $ mkeficapsule -f <firmware binary> <output file>
  154. */
  155. int main(int argc, char **argv)
  156. {
  157. char *file;
  158. efi_guid_t *guid;
  159. unsigned long index, instance;
  160. int c, idx;
  161. file = NULL;
  162. guid = NULL;
  163. index = 0;
  164. instance = 0;
  165. for (;;) {
  166. c = getopt_long(argc, argv, "f:r:i:I:v:h", options, &idx);
  167. if (c == -1)
  168. break;
  169. switch (c) {
  170. case 'f':
  171. if (file) {
  172. printf("Image already specified\n");
  173. return -1;
  174. }
  175. file = optarg;
  176. guid = &efi_guid_image_type_uboot_fit;
  177. break;
  178. case 'r':
  179. if (file) {
  180. printf("Image already specified\n");
  181. return -1;
  182. }
  183. file = optarg;
  184. guid = &efi_guid_image_type_uboot_raw;
  185. break;
  186. case 'i':
  187. index = strtoul(optarg, NULL, 0);
  188. break;
  189. case 'I':
  190. instance = strtoul(optarg, NULL, 0);
  191. break;
  192. case 'h':
  193. print_usage();
  194. return 0;
  195. }
  196. }
  197. /* need an output file */
  198. if (argc != optind + 1) {
  199. print_usage();
  200. exit(EXIT_FAILURE);
  201. }
  202. /* need a fit image file or raw image file */
  203. if (!file) {
  204. print_usage();
  205. exit(EXIT_SUCCESS);
  206. }
  207. if (create_fwbin(argv[optind], file, guid, index, instance)
  208. < 0) {
  209. printf("Creating firmware capsule failed\n");
  210. exit(EXIT_FAILURE);
  211. }
  212. exit(EXIT_SUCCESS);
  213. }