1 /*
2  * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <string.h>
9 #include <stdbool.h>
10 #include "tfm_hal_device_header.h"
11 #include "uefi_fmp.h"
12 
13 /* The count will increase when partial update is supported.
14  * At present, only full WIC is considered as updatable image.
15  */
16 #define NUMBER_OF_FMP_IMAGES 1
17 #define NO_OF_FMP_VARIABLES_PER_IMAGE   6
18 
19 #define UEFI_ARCHITECTURE_64
20 
21 #ifdef UEFI_ARCHITECTURE_64
22 typedef uint64_t uefi_ptr_t;
23 typedef uint64_t efi_uintn_t;
24 #else
25 typedef uint32_t uefi_ptr_t;
26 typedef uint32_t efi_uintn_t;
27 #endif
28 
29 /* Below macro definations and struct declarations taken from UEFI spec 2.9 */
30 
31 /*
32  * Image Attribute Definitions
33  */
34 #define IMAGE_ATTRIBUTE_IMAGE_UPDATABLE            0x00000001
35 #define IMAGE_ATTRIBUTE_RESET_REQUIRED             0x00000002
36 #define IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED    0x00000004
37 #define IMAGE_ATTRIBUTE_IN_USE                     0x00000008
38 #define IMAGE_ATTRIBUTE_UEFI_IMAGE                 0x00000010
39 #define IMAGE_ATTRIBUTE_DEPENDENCY                 0x00000020
40 
41 typedef uint32_t DescriptorVersion_t;
42 typedef uint32_t DescriptorSize_t;
43 typedef uint8_t DescriptorCount_t;
44 
45 typedef __PACKED_STRUCT {
46     uint8_t ImageIndex;
47     struct efi_guid ImageTypeId;
48     uint64_t ImageId;
49     uefi_ptr_t PtrImageIdName;
50     uint32_t Version;
51     uefi_ptr_t PtrVersionName;
52     efi_uintn_t Size;
53     uint64_t AttributesSupported;
54     uint64_t AttributesSetting;
55     uint64_t Compatibilities;
56     /* Introduced with DescriptorVersion 2+ */
57     uint32_t LowestSupportedImageVersion;
58     /* Introduced with DescriptorVersion 3+ */
59     uint32_t LastAttemptVersion;
60     uint32_t LastAttemptStatus;
61     uint64_t HardwareInstance;
62     /* Introduced with DescriptorVersion 4+ */
63     uefi_ptr_t PtrDependencies;
64 } EFI_FIRMWARE_IMAGE_DESCRIPTOR;
65 
66 typedef __PACKED_STRUCT {
67     DescriptorVersion_t DescriptorVersion;
68     DescriptorSize_t DescriptorsSize;
69     DescriptorCount_t DescriptorCount;
70     EFI_FIRMWARE_IMAGE_DESCRIPTOR ImageDescriptor;
71     uint16_t *ImageName;
72     uint32_t ImageNameSize;
73     uint16_t *ImageVersionName;
74     uint32_t ImageVersionNameSize;
75 } EFI_FIRMWARE_MANAGEMENT_PROTOCOL_IMAGE_INFO;
76 
77 
78 static uint16_t corstone_image_name0[] = { 'C', 'O', 'R', 'S', 'T', 'O', 'N', 'E', '1', '0', '0', '0', '_', 'W', 'I', 'C', '\0' };
79 static uint16_t corstone_version_name0[] = { 'C', 'O', 'R', 'S', 'T', 'O', 'N', 'E', '1', '0', '0', '0', '_', 'B', 'E', 'S', 'T', '\0'};
80 
81 static EFI_FIRMWARE_MANAGEMENT_PROTOCOL_IMAGE_INFO fmp_info[NUMBER_OF_FMP_IMAGES];
82 
83 extern struct efi_guid full_capsule_image_guid;
84 
85 static bool is_fmp_info_initialized = false;
86 
init_fmp_info(void)87 static void init_fmp_info(void)
88 {
89     memset(fmp_info, 0,
90      sizeof(EFI_FIRMWARE_MANAGEMENT_PROTOCOL_IMAGE_INFO) * NUMBER_OF_FMP_IMAGES);
91 
92     /* Fill information for the WIC.
93      * Add further details when partial image is supported.
94      */
95 
96     fmp_info[0].DescriptorVersion = 4;
97     fmp_info[0].DescriptorCount = NUMBER_OF_FMP_IMAGES;
98     fmp_info[0].DescriptorsSize =
99                  sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) +
100                  sizeof(corstone_image_name0) + sizeof(corstone_version_name0);
101 
102     fmp_info[0].ImageDescriptor.ImageIndex = 1;
103 
104     memcpy(&fmp_info[0].ImageDescriptor.ImageTypeId, &full_capsule_image_guid,
105             sizeof(struct efi_guid));
106 
107     fmp_info[0].ImageDescriptor.ImageId = 1;
108     fmp_info[0].ImageDescriptor.Version = FWU_IMAGE_INITIAL_VERSION;
109     fmp_info[0].ImageDescriptor.AttributesSupported = 1;
110     fmp_info[0].ImageDescriptor.AttributesSetting = (
111             IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | IMAGE_ATTRIBUTE_RESET_REQUIRED);
112     fmp_info[0].ImageDescriptor.LowestSupportedImageVersion =
113             FWU_IMAGE_INITIAL_VERSION;
114     fmp_info[0].ImageDescriptor.LastAttemptVersion = FWU_IMAGE_INITIAL_VERSION;
115     fmp_info[0].ImageDescriptor.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
116 
117     fmp_info[0].ImageName = corstone_image_name0;
118     fmp_info[0].ImageNameSize = sizeof(corstone_image_name0);
119     fmp_info[0].ImageVersionName = corstone_version_name0;
120     fmp_info[0].ImageVersionNameSize = sizeof(corstone_version_name0);
121 
122     is_fmp_info_initialized = true;
123 
124     return;
125 }
126 
fmp_set_image_info(struct efi_guid * guid,uint32_t current_version,uint32_t attempt_version,uint32_t last_attempt_status)127 enum fwu_agent_error_t fmp_set_image_info(struct efi_guid *guid,
128                      uint32_t current_version, uint32_t attempt_version,
129                      uint32_t last_attempt_status)
130 {
131     enum fwu_agent_error_t status = FWU_AGENT_ERROR;
132 
133     FWU_LOG_MSG("%s:%d Enter\n\r", __func__, __LINE__);
134 
135     if (is_fmp_info_initialized == false) {
136         init_fmp_info();
137     }
138 
139     for (int i = 0; i < NUMBER_OF_FMP_IMAGES; i++) {
140         if ((memcmp(guid, &fmp_info[i].ImageDescriptor.ImageTypeId,
141                         sizeof(struct efi_guid))) == 0)
142         {
143             FWU_LOG_MSG("FMP image update: image id = %u\n\r",
144                                     fmp_info[i].ImageDescriptor.ImageId);
145             fmp_info[i].ImageDescriptor.Version = current_version;
146             fmp_info[i].ImageDescriptor.LastAttemptVersion = attempt_version;
147             fmp_info[i].ImageDescriptor.LastAttemptStatus = last_attempt_status;
148             FWU_LOG_MSG("FMP image update: status = %u"
149                             "version=%u last_attempt_version=%u.\n\r",
150                             last_attempt_status, current_version,
151                             attempt_version);
152             status = FWU_AGENT_SUCCESS;
153             break;
154         }
155     }
156 
157     FWU_LOG_MSG("%s:%d Exit.\n\r", __func__, __LINE__);
158     return status;
159 }
160 
161 
162 #define NO_OF_FMP_VARIABLES    (NUMBER_OF_FMP_IMAGES * NO_OF_FMP_VARIABLES_PER_IMAGE)
163 
pack_image_info(void * buffer,uint32_t size)164 static enum fwu_agent_error_t pack_image_info(void *buffer, uint32_t size)
165 {
166     typedef __PACKED_STRUCT {
167         uint32_t variable_count;
168         uint32_t variable_size[NO_OF_FMP_VARIABLES];
169         uint8_t variable[];
170     } packed_buffer_t;
171 
172     packed_buffer_t *packed_buffer = buffer;
173     int runner = 0;
174     int index = 0;
175     int current_size = sizeof(packed_buffer_t);
176     int size_requirement_1 = 0;
177     int size_requirement_2 = 0;
178 
179     if (size < current_size) {
180         FWU_LOG_MSG("%s:%d Buffer too small.\n\r", __func__, __LINE__);
181         return FWU_AGENT_ERROR;
182     }
183 
184     packed_buffer->variable_count = NO_OF_FMP_VARIABLES;
185 
186     for (int i = 0; i < NUMBER_OF_FMP_IMAGES; i++) {
187 
188        packed_buffer->variable_size[index++] = sizeof(DescriptorVersion_t);
189        packed_buffer->variable_size[index++] = sizeof(DescriptorSize_t);
190        packed_buffer->variable_size[index++] = sizeof(DescriptorCount_t);
191        packed_buffer->variable_size[index++] = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR);
192        packed_buffer->variable_size[index++] = fmp_info[i].ImageNameSize;
193        packed_buffer->variable_size[index++] = fmp_info[i].ImageVersionNameSize;
194 
195        size_requirement_1 = sizeof(DescriptorVersion_t) + sizeof(DescriptorSize_t) +
196               sizeof(DescriptorCount_t) + sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR);
197 
198        size_requirement_2 = fmp_info[i].ImageNameSize + fmp_info[i].ImageVersionNameSize;
199 
200        current_size += size_requirement_1 + size_requirement_2;
201 
202        if (size < current_size) {
203            FWU_LOG_MSG("%s:%d Buffer too small.\n\r", __func__, __LINE__);
204            return FWU_AGENT_ERROR;
205        }
206 
207        FWU_LOG_MSG("%s:%d ImageInfo size = %u, ImageName size = %u, "
208                "ImageVersionName size = %u\n\r", __func__, __LINE__,
209                sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR), fmp_info[i].ImageNameSize,
210                fmp_info[i].ImageVersionNameSize);
211 
212        memcpy(&packed_buffer->variable[runner], &fmp_info[i], size_requirement_1);
213        runner += size_requirement_1;
214 
215        memcpy(&packed_buffer->variable[runner], fmp_info[i].ImageName,
216                                        fmp_info[i].ImageNameSize);
217        runner += fmp_info[i].ImageNameSize;
218 
219        memcpy(&packed_buffer->variable[runner], fmp_info[i].ImageVersionName,
220                                        fmp_info[i].ImageVersionNameSize);
221        runner += fmp_info[i].ImageVersionNameSize;
222 
223     }
224 
225     return FWU_AGENT_SUCCESS;
226 }
227 
fmp_get_image_info(void * buffer,uint32_t size)228 enum fwu_agent_error_t fmp_get_image_info(void *buffer, uint32_t size)
229 {
230     enum fwu_agent_error_t status;
231 
232     FWU_LOG_MSG("%s:%d Enter\n\r", __func__, __LINE__);
233 
234     status = pack_image_info(buffer, size);
235 
236     FWU_LOG_MSG("%s:%d Exit\n\r", __func__, __LINE__);
237 
238     return status;
239 }
240 
241