fwu_gpt.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (c) 2022, Linaro Limited
  4. */
  5. #include <blk.h>
  6. #include <dfu.h>
  7. #include <efi.h>
  8. #include <efi_loader.h>
  9. #include <fwu.h>
  10. #include <log.h>
  11. #include <part.h>
  12. #include <linux/errno.h>
  13. static int get_gpt_dfu_identifier(struct blk_desc *desc, efi_guid_t *image_guid)
  14. {
  15. int i;
  16. struct disk_partition info;
  17. efi_guid_t unique_part_guid;
  18. for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) {
  19. if (part_get_info(desc, i, &info))
  20. continue;
  21. uuid_str_to_bin(info.uuid, unique_part_guid.b,
  22. UUID_STR_FORMAT_GUID);
  23. if (!guidcmp(&unique_part_guid, image_guid))
  24. return i;
  25. }
  26. log_err("No partition found with image_guid %pUs\n", image_guid);
  27. return -ENOENT;
  28. }
  29. static int fwu_alt_num_for_dfu_dev(struct dfu_entity *dfu, int dev_num,
  30. int part, unsigned char dfu_dev,
  31. u8 *alt_num)
  32. {
  33. int ret;
  34. switch(dfu_dev) {
  35. case DFU_DEV_MMC:
  36. if (dfu->layout == DFU_RAW_ADDR &&
  37. dfu->data.mmc.dev_num == dev_num &&
  38. dfu->data.mmc.part == part) {
  39. *alt_num = dfu->alt;
  40. ret = 0;
  41. } else {
  42. ret = -ENOENT;
  43. }
  44. break;
  45. default:
  46. ret = -ENOENT;
  47. }
  48. return ret;
  49. }
  50. static int fwu_gpt_get_alt_num(struct blk_desc *desc, efi_guid_t *image_guid,
  51. u8 *alt_num, unsigned char dfu_dev)
  52. {
  53. int ret = -1;
  54. int i, part, dev_num;
  55. struct dfu_entity *dfu;
  56. dev_num = desc->devnum;
  57. part = get_gpt_dfu_identifier(desc, image_guid);
  58. if (part < 0)
  59. return -ENOENT;
  60. ret = dfu_init_env_entities(NULL, NULL);
  61. if (ret)
  62. goto out;
  63. i = 0;
  64. while (true) {
  65. dfu = dfu_get_entity(i++);
  66. if (!dfu) {
  67. ret = -ENOENT;
  68. break;
  69. }
  70. if (dfu->dev_type != dfu_dev)
  71. continue;
  72. ret = fwu_alt_num_for_dfu_dev(dfu, dev_num, part, dfu_dev,
  73. alt_num);
  74. if (!ret)
  75. break;
  76. }
  77. out:
  78. dfu_free_entities();
  79. return ret;
  80. }
  81. /**
  82. * fwu_plat_get_alt_num() - Get the DFU alt number
  83. * @dev: FWU metadata device
  84. * @image_guid: GUID value of the image for which the alt num is to
  85. * be obtained
  86. * @alt_num: The DFU alt number for the image that is to be updated
  87. *
  88. * Get the DFU alt number for the image that is to be updated. The
  89. * image is identified with the image_guid parameter that is passed
  90. * to the function.
  91. *
  92. * Note: This is a weak function and platforms can override this with
  93. * their own implementation for obtaining the alt number value.
  94. *
  95. * Return: 0 if OK, -ve on error
  96. *
  97. */
  98. __weak int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid,
  99. u8 *alt_num)
  100. {
  101. struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
  102. return fwu_gpt_get_alt_num(dev_get_uclass_plat(priv->blk_dev),
  103. image_guid, alt_num, DFU_DEV_MMC);
  104. }