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