efi_firmware.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * EFI Firmware management protocol
  4. *
  5. * Copyright (c) 2020 Linaro Limited
  6. * Author: AKASHI Takahiro
  7. */
  8. #include <common.h>
  9. #include <charset.h>
  10. #include <dfu.h>
  11. #include <efi_loader.h>
  12. #include <image.h>
  13. #include <signatures.h>
  14. #include <linux/list.h>
  15. #define FMP_PAYLOAD_HDR_SIGNATURE SIGNATURE_32('M', 'S', 'S', '1')
  16. /**
  17. * struct fmp_payload_header - EDK2 header for the FMP payload
  18. *
  19. * This structure describes the header which is preprended to the
  20. * FMP payload by the edk2 capsule generation scripts.
  21. *
  22. * @signature: Header signature used to identify the header
  23. * @header_size: Size of the structure
  24. * @fw_version: Firmware versions used
  25. * @lowest_supported_version: Lowest supported version
  26. */
  27. struct fmp_payload_header {
  28. u32 signature;
  29. u32 header_size;
  30. u32 fw_version;
  31. u32 lowest_supported_version;
  32. };
  33. /* Place holder; not supported */
  34. static
  35. efi_status_t EFIAPI efi_firmware_get_image_unsupported(
  36. struct efi_firmware_management_protocol *this,
  37. u8 image_index,
  38. void *image,
  39. efi_uintn_t *image_size)
  40. {
  41. EFI_ENTRY("%p %d %p %p\n", this, image_index, image, image_size);
  42. return EFI_EXIT(EFI_UNSUPPORTED);
  43. }
  44. /* Place holder; not supported */
  45. static
  46. efi_status_t EFIAPI efi_firmware_check_image_unsupported(
  47. struct efi_firmware_management_protocol *this,
  48. u8 image_index,
  49. const void *image,
  50. efi_uintn_t *image_size,
  51. u32 *image_updatable)
  52. {
  53. EFI_ENTRY("%p %d %p %p %p\n", this, image_index, image, image_size,
  54. image_updatable);
  55. return EFI_EXIT(EFI_UNSUPPORTED);
  56. }
  57. /* Place holder; not supported */
  58. static
  59. efi_status_t EFIAPI efi_firmware_get_package_info_unsupported(
  60. struct efi_firmware_management_protocol *this,
  61. u32 *package_version,
  62. u16 **package_version_name,
  63. u32 *package_version_name_maxlen,
  64. u64 *attributes_supported,
  65. u64 *attributes_setting)
  66. {
  67. EFI_ENTRY("%p %p %p %p %p %p\n", this, package_version,
  68. package_version_name, package_version_name_maxlen,
  69. attributes_supported, attributes_setting);
  70. return EFI_EXIT(EFI_UNSUPPORTED);
  71. }
  72. /* Place holder; not supported */
  73. static
  74. efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
  75. struct efi_firmware_management_protocol *this,
  76. const void *image,
  77. efi_uintn_t *image_size,
  78. const void *vendor_code,
  79. u32 package_version,
  80. const u16 *package_version_name)
  81. {
  82. EFI_ENTRY("%p %p %p %p %x %p\n", this, image, image_size, vendor_code,
  83. package_version, package_version_name);
  84. return EFI_EXIT(EFI_UNSUPPORTED);
  85. }
  86. /**
  87. * efi_get_dfu_info - return information about the current firmware image
  88. * @this: Protocol instance
  89. * @image_info_size: Size of @image_info
  90. * @image_info: Image information
  91. * @descriptor_version: Pointer to version number
  92. * @descriptor_count: Pointer to number of descriptors
  93. * @descriptor_size: Pointer to descriptor size
  94. * package_version: Package version
  95. * package_version_name: Package version's name
  96. * image_type: Image type GUID
  97. *
  98. * Return information bout the current firmware image in @image_info.
  99. * @image_info will consist of a number of descriptors.
  100. * Each descriptor will be created based on "dfu_alt_info" variable.
  101. *
  102. * Return status code
  103. */
  104. static efi_status_t efi_get_dfu_info(
  105. efi_uintn_t *image_info_size,
  106. struct efi_firmware_image_descriptor *image_info,
  107. u32 *descriptor_version,
  108. u8 *descriptor_count,
  109. efi_uintn_t *descriptor_size,
  110. u32 *package_version,
  111. u16 **package_version_name,
  112. const efi_guid_t *image_type)
  113. {
  114. struct dfu_entity *dfu;
  115. size_t names_len, total_size;
  116. int dfu_num, i;
  117. u16 *name, *next;
  118. dfu_init_env_entities(NULL, NULL);
  119. names_len = 0;
  120. dfu_num = 0;
  121. list_for_each_entry(dfu, &dfu_list, list) {
  122. names_len += (utf8_utf16_strlen(dfu->name) + 1) * 2;
  123. dfu_num++;
  124. }
  125. if (!dfu_num) {
  126. log_warning("Probably dfu_alt_info not defined\n");
  127. *image_info_size = 0;
  128. dfu_free_entities();
  129. return EFI_SUCCESS;
  130. }
  131. total_size = sizeof(*image_info) * dfu_num + names_len;
  132. /*
  133. * we will assume that sizeof(*image_info) * dfu_name
  134. * is, at least, a multiple of 2. So the start address for
  135. * image_id_name would be aligned with 2 bytes.
  136. */
  137. if (*image_info_size < total_size) {
  138. *image_info_size = total_size;
  139. dfu_free_entities();
  140. return EFI_BUFFER_TOO_SMALL;
  141. }
  142. *image_info_size = total_size;
  143. *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
  144. *descriptor_count = dfu_num;
  145. *descriptor_size = sizeof(*image_info);
  146. *package_version = 0xffffffff; /* not supported */
  147. *package_version_name = NULL; /* not supported */
  148. /* DFU alt number should correspond to image_index */
  149. i = 0;
  150. /* Name area starts just after descriptors */
  151. name = (u16 *)((u8 *)image_info + sizeof(*image_info) * dfu_num);
  152. next = name;
  153. list_for_each_entry(dfu, &dfu_list, list) {
  154. image_info[i].image_index = dfu->alt + 1;
  155. image_info[i].image_type_id = *image_type;
  156. image_info[i].image_id = dfu->alt;
  157. /* copy the DFU entity name */
  158. utf8_utf16_strcpy(&next, dfu->name);
  159. image_info[i].image_id_name = name;
  160. name = ++next;
  161. image_info[i].version = 0; /* not supported */
  162. image_info[i].version_name = NULL; /* not supported */
  163. image_info[i].size = 0;
  164. image_info[i].attributes_supported =
  165. IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
  166. IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED;
  167. image_info[i].attributes_setting =
  168. IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
  169. /* Check if the capsule authentication is enabled */
  170. if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE))
  171. image_info[0].attributes_setting |=
  172. IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED;
  173. image_info[i].lowest_supported_image_version = 0;
  174. image_info[i].last_attempt_version = 0;
  175. image_info[i].last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS;
  176. image_info[i].hardware_instance = 1;
  177. image_info[i].dependencies = NULL;
  178. i++;
  179. }
  180. dfu_free_entities();
  181. return EFI_SUCCESS;
  182. }
  183. #ifdef CONFIG_EFI_CAPSULE_FIRMWARE_FIT
  184. /*
  185. * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
  186. * method with existing FIT image format, and handles
  187. * - multiple regions of firmware via DFU
  188. * but doesn't support
  189. * - versioning of firmware image
  190. * - package information
  191. */
  192. const efi_guid_t efi_firmware_image_type_uboot_fit =
  193. EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID;
  194. /**
  195. * efi_firmware_fit_get_image_info - return information about the current
  196. * firmware image
  197. * @this: Protocol instance
  198. * @image_info_size: Size of @image_info
  199. * @image_info: Image information
  200. * @descriptor_version: Pointer to version number
  201. * @descriptor_count: Pointer to number of descriptors
  202. * @descriptor_size: Pointer to descriptor size
  203. * package_version: Package version
  204. * package_version_name: Package version's name
  205. *
  206. * Return information bout the current firmware image in @image_info.
  207. * @image_info will consist of a number of descriptors.
  208. * Each descriptor will be created based on "dfu_alt_info" variable.
  209. *
  210. * Return status code
  211. */
  212. static
  213. efi_status_t EFIAPI efi_firmware_fit_get_image_info(
  214. struct efi_firmware_management_protocol *this,
  215. efi_uintn_t *image_info_size,
  216. struct efi_firmware_image_descriptor *image_info,
  217. u32 *descriptor_version,
  218. u8 *descriptor_count,
  219. efi_uintn_t *descriptor_size,
  220. u32 *package_version,
  221. u16 **package_version_name)
  222. {
  223. efi_status_t ret;
  224. EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
  225. image_info_size, image_info,
  226. descriptor_version, descriptor_count, descriptor_size,
  227. package_version, package_version_name);
  228. if (!image_info_size)
  229. return EFI_EXIT(EFI_INVALID_PARAMETER);
  230. if (*image_info_size &&
  231. (!image_info || !descriptor_version || !descriptor_count ||
  232. !descriptor_size || !package_version || !package_version_name))
  233. return EFI_EXIT(EFI_INVALID_PARAMETER);
  234. ret = efi_get_dfu_info(image_info_size, image_info,
  235. descriptor_version, descriptor_count,
  236. descriptor_size,
  237. package_version, package_version_name,
  238. &efi_firmware_image_type_uboot_fit);
  239. return EFI_EXIT(ret);
  240. }
  241. /**
  242. * efi_firmware_fit_set_image - update the firmware image
  243. * @this: Protocol instance
  244. * @image_index: Image index number
  245. * @image: New image
  246. * @image_size: Size of new image
  247. * @vendor_code: Vendor-specific update policy
  248. * @progress: Function to report the progress of update
  249. * @abort_reason: Pointer to string of abort reason
  250. *
  251. * Update the firmware to new image, using dfu. The new image should
  252. * have FIT image format commonly used in U-Boot.
  253. * @vendor_code, @progress and @abort_reason are not supported.
  254. *
  255. * Return: status code
  256. */
  257. static
  258. efi_status_t EFIAPI efi_firmware_fit_set_image(
  259. struct efi_firmware_management_protocol *this,
  260. u8 image_index,
  261. const void *image,
  262. efi_uintn_t image_size,
  263. const void *vendor_code,
  264. efi_status_t (*progress)(efi_uintn_t completion),
  265. u16 **abort_reason)
  266. {
  267. EFI_ENTRY("%p %d %p %zd %p %p %p\n", this, image_index, image,
  268. image_size, vendor_code, progress, abort_reason);
  269. if (!image || image_index != 1)
  270. return EFI_EXIT(EFI_INVALID_PARAMETER);
  271. if (fit_update(image))
  272. return EFI_EXIT(EFI_DEVICE_ERROR);
  273. return EFI_EXIT(EFI_SUCCESS);
  274. }
  275. const struct efi_firmware_management_protocol efi_fmp_fit = {
  276. .get_image_info = efi_firmware_fit_get_image_info,
  277. .get_image = efi_firmware_get_image_unsupported,
  278. .set_image = efi_firmware_fit_set_image,
  279. .check_image = efi_firmware_check_image_unsupported,
  280. .get_package_info = efi_firmware_get_package_info_unsupported,
  281. .set_package_info = efi_firmware_set_package_info_unsupported,
  282. };
  283. #endif /* CONFIG_EFI_CAPSULE_FIRMWARE_FIT */
  284. #ifdef CONFIG_EFI_CAPSULE_FIRMWARE_RAW
  285. /*
  286. * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update
  287. * method with raw data.
  288. */
  289. const efi_guid_t efi_firmware_image_type_uboot_raw =
  290. EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID;
  291. /**
  292. * efi_firmware_raw_get_image_info - return information about the current
  293. firmware image
  294. * @this: Protocol instance
  295. * @image_info_size: Size of @image_info
  296. * @image_info: Image information
  297. * @descriptor_version: Pointer to version number
  298. * @descriptor_count: Pointer to number of descriptors
  299. * @descriptor_size: Pointer to descriptor size
  300. * package_version: Package version
  301. * package_version_name: Package version's name
  302. *
  303. * Return information bout the current firmware image in @image_info.
  304. * @image_info will consist of a number of descriptors.
  305. * Each descriptor will be created based on "dfu_alt_info" variable.
  306. *
  307. * Return status code
  308. */
  309. static
  310. efi_status_t EFIAPI efi_firmware_raw_get_image_info(
  311. struct efi_firmware_management_protocol *this,
  312. efi_uintn_t *image_info_size,
  313. struct efi_firmware_image_descriptor *image_info,
  314. u32 *descriptor_version,
  315. u8 *descriptor_count,
  316. efi_uintn_t *descriptor_size,
  317. u32 *package_version,
  318. u16 **package_version_name)
  319. {
  320. efi_status_t ret = EFI_SUCCESS;
  321. EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
  322. image_info_size, image_info,
  323. descriptor_version, descriptor_count, descriptor_size,
  324. package_version, package_version_name);
  325. if (!image_info_size)
  326. return EFI_EXIT(EFI_INVALID_PARAMETER);
  327. if (*image_info_size &&
  328. (!image_info || !descriptor_version || !descriptor_count ||
  329. !descriptor_size || !package_version || !package_version_name))
  330. return EFI_EXIT(EFI_INVALID_PARAMETER);
  331. ret = efi_get_dfu_info(image_info_size, image_info,
  332. descriptor_version, descriptor_count,
  333. descriptor_size,
  334. package_version, package_version_name,
  335. &efi_firmware_image_type_uboot_raw);
  336. return EFI_EXIT(ret);
  337. }
  338. /**
  339. * efi_firmware_raw_set_image - update the firmware image
  340. * @this: Protocol instance
  341. * @image_index: Image index number
  342. * @image: New image
  343. * @image_size: Size of new image
  344. * @vendor_code: Vendor-specific update policy
  345. * @progress: Function to report the progress of update
  346. * @abort_reason: Pointer to string of abort reason
  347. *
  348. * Update the firmware to new image, using dfu. The new image should
  349. * be a single raw image.
  350. * @vendor_code, @progress and @abort_reason are not supported.
  351. *
  352. * Return: status code
  353. */
  354. static
  355. efi_status_t EFIAPI efi_firmware_raw_set_image(
  356. struct efi_firmware_management_protocol *this,
  357. u8 image_index,
  358. const void *image,
  359. efi_uintn_t image_size,
  360. const void *vendor_code,
  361. efi_status_t (*progress)(efi_uintn_t completion),
  362. u16 **abort_reason)
  363. {
  364. u32 fmp_hdr_signature;
  365. struct fmp_payload_header *header;
  366. void *capsule_payload;
  367. efi_status_t status;
  368. efi_uintn_t capsule_payload_size;
  369. EFI_ENTRY("%p %d %p %zd %p %p %p\n", this, image_index, image,
  370. image_size, vendor_code, progress, abort_reason);
  371. if (!image)
  372. return EFI_EXIT(EFI_INVALID_PARAMETER);
  373. /* Authenticate the capsule if authentication enabled */
  374. if (IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)) {
  375. capsule_payload = NULL;
  376. capsule_payload_size = 0;
  377. status = efi_capsule_authenticate(image, image_size,
  378. &capsule_payload,
  379. &capsule_payload_size);
  380. if (status == EFI_SECURITY_VIOLATION) {
  381. printf("Capsule authentication check failed. Aborting update\n");
  382. return EFI_EXIT(status);
  383. } else if (status != EFI_SUCCESS) {
  384. return EFI_EXIT(status);
  385. }
  386. debug("Capsule authentication successfull\n");
  387. image = capsule_payload;
  388. image_size = capsule_payload_size;
  389. } else {
  390. debug("Capsule authentication disabled. ");
  391. debug("Updating capsule without authenticating.\n");
  392. }
  393. fmp_hdr_signature = FMP_PAYLOAD_HDR_SIGNATURE;
  394. header = (void *)image;
  395. if (!memcmp(&header->signature, &fmp_hdr_signature,
  396. sizeof(fmp_hdr_signature))) {
  397. /*
  398. * When building the capsule with the scripts in
  399. * edk2, a FMP header is inserted above the capsule
  400. * payload. Compensate for this header to get the
  401. * actual payload that is to be updated.
  402. */
  403. image += header->header_size;
  404. image_size -= header->header_size;
  405. }
  406. if (dfu_write_by_alt(image_index - 1, (void *)image, image_size,
  407. NULL, NULL))
  408. return EFI_EXIT(EFI_DEVICE_ERROR);
  409. return EFI_EXIT(EFI_SUCCESS);
  410. }
  411. const struct efi_firmware_management_protocol efi_fmp_raw = {
  412. .get_image_info = efi_firmware_raw_get_image_info,
  413. .get_image = efi_firmware_get_image_unsupported,
  414. .set_image = efi_firmware_raw_set_image,
  415. .check_image = efi_firmware_check_image_unsupported,
  416. .get_package_info = efi_firmware_get_package_info_unsupported,
  417. .set_package_info = efi_firmware_set_package_info_unsupported,
  418. };
  419. #endif /* CONFIG_EFI_CAPSULE_FIRMWARE_RAW */