blob: 2a31d37f9cf3719360b16dfa7c9a0e5d4fc76e05 [file] [log] [blame]
Tom Rini8b0c8a12018-05-06 18:27:01 -04001// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
Patrick Delaunaye6db5df2018-03-12 10:46:04 +01002/*
3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
Patrick Delaunaye6db5df2018-03-12 10:46:04 +01004 */
5
6#include <image.h>
7#include "imagetool.h"
8
9/* magic ='S' 'T' 'M' 0x32 */
10#define HEADER_MAGIC be32_to_cpu(0x53544D32)
Marek Vasut076cdf72025-05-12 19:09:47 +020011#define VER_MAJOR 2
12#define VER_MINOR 1
13#define VER_VARIANT 0
Patrick Delaunaye6db5df2018-03-12 10:46:04 +010014#define HEADER_VERSION_V1 0x1
Marek Vasut076cdf72025-05-12 19:09:47 +020015#define HEADER_VERSION_V2 0x2
Patrick Delaunaye6db5df2018-03-12 10:46:04 +010016/* default option : bit0 => no signature */
17#define HEADER_DEFAULT_OPTION (cpu_to_le32(0x00000001))
Patrick Delaunay3b59d222019-04-18 17:32:44 +020018/* default binary type for U-Boot */
19#define HEADER_TYPE_UBOOT (cpu_to_le32(0x00000000))
Marek Vasut076cdf72025-05-12 19:09:47 +020020#define PADDING_HEADER_MAGIC (cpu_to_le32(0xFFFF5453))
21#define PADDING_HEADER_FLAG (1ULL << 31)
22#define PADDING_HEADER_LENGTH 0x180
Patrick Delaunaye6db5df2018-03-12 10:46:04 +010023
Marek Vasut076cdf72025-05-12 19:09:47 +020024struct stm32_header_v1 {
Patrick Delaunaye6db5df2018-03-12 10:46:04 +010025 uint32_t magic_number;
Marek Vasut076cdf72025-05-12 19:09:47 +020026 uint8_t image_signature[64];
Patrick Delaunaye6db5df2018-03-12 10:46:04 +010027 uint32_t image_checksum;
Marek Vasut076cdf72025-05-12 19:09:47 +020028 uint8_t header_version[4];
Patrick Delaunaye6db5df2018-03-12 10:46:04 +010029 uint32_t image_length;
30 uint32_t image_entry_point;
31 uint32_t reserved1;
32 uint32_t load_address;
33 uint32_t reserved2;
34 uint32_t version_number;
Marek Vasut076cdf72025-05-12 19:09:47 +020035 /* V1.0 specific content */
Patrick Delaunaye6db5df2018-03-12 10:46:04 +010036 uint32_t option_flags;
37 uint32_t ecdsa_algorithm;
Marek Vasut076cdf72025-05-12 19:09:47 +020038 uint8_t ecdsa_public_key[64];
39 uint8_t padding[83];
40 uint8_t binary_type;
Patrick Delaunaye6db5df2018-03-12 10:46:04 +010041};
42
Marek Vasut076cdf72025-05-12 19:09:47 +020043struct stm32_header_v2 {
44 uint32_t magic_number;
45 uint8_t image_signature[64];
46 uint32_t image_checksum;
47 uint8_t header_version[4];
48 uint32_t image_length;
49 uint32_t image_entry_point;
50 uint32_t reserved1;
51 uint32_t load_address;
52 uint32_t reserved2;
53 uint32_t version_number;
54 /* V2.0 specific content */
55 uint32_t extension_flags;
56 uint32_t extension_headers_length;
57 uint32_t binary_type;
58 uint8_t padding[16];
59 uint32_t extension_header_type;
60 uint32_t extension_header_length;
61 uint8_t extension_padding[376];
62};
Patrick Delaunaye6db5df2018-03-12 10:46:04 +010063
Marek Vasut076cdf72025-05-12 19:09:47 +020064static struct stm32_header_v1 stm32image_header_v1;
65static struct stm32_header_v2 stm32image_header_v2;
Patrick Delaunaye6db5df2018-03-12 10:46:04 +010066
Marek Vasut076cdf72025-05-12 19:09:47 +020067static uint32_t stm32image_checksum(void *start, uint32_t len,
68 uint32_t header_size)
Patrick Delaunaye6db5df2018-03-12 10:46:04 +010069{
70 uint32_t csum = 0;
Patrick Delaunaye6db5df2018-03-12 10:46:04 +010071 uint8_t *p;
72
Marek Vasut076cdf72025-05-12 19:09:47 +020073 if (len < header_size) {
Patrick Delaunaye6db5df2018-03-12 10:46:04 +010074 return 0;
Marek Vasut076cdf72025-05-12 19:09:47 +020075 }
Patrick Delaunaye6db5df2018-03-12 10:46:04 +010076
Marek Vasut076cdf72025-05-12 19:09:47 +020077 p = (unsigned char *)start + header_size;
78 len -= header_size;
Patrick Delaunaye6db5df2018-03-12 10:46:04 +010079
80 while (len > 0) {
81 csum += *p;
82 p++;
83 len--;
84 }
85
86 return csum;
87}
88
Marek Vasut076cdf72025-05-12 19:09:47 +020089static int stm32image_check_image_types_v1(uint8_t type)
Patrick Delaunaye6db5df2018-03-12 10:46:04 +010090{
91 if (type == IH_TYPE_STM32IMAGE)
92 return EXIT_SUCCESS;
93 return EXIT_FAILURE;
94}
95
Marek Vasut076cdf72025-05-12 19:09:47 +020096static int stm32image_check_image_types_v2(uint8_t type)
Patrick Delaunaye6db5df2018-03-12 10:46:04 +010097{
Marek Vasut076cdf72025-05-12 19:09:47 +020098 if (type == IH_TYPE_STM32IMAGE_V2)
99 return EXIT_SUCCESS;
100 return EXIT_FAILURE;
101}
102
103static int stm32image_verify_header_v1(unsigned char *ptr, int image_size,
104 struct image_tool_params *params)
105{
106 struct stm32_header_v1 *stm32hdr = (struct stm32_header_v1 *)ptr;
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100107 int i;
108
Marek Vasut076cdf72025-05-12 19:09:47 +0200109 if (image_size < sizeof(struct stm32_header_v1))
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100110 return -1;
111 if (stm32hdr->magic_number != HEADER_MAGIC)
112 return -1;
Marek Vasut076cdf72025-05-12 19:09:47 +0200113 if (stm32hdr->header_version[VER_MAJOR] != HEADER_VERSION_V1)
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100114 return -1;
115 if (stm32hdr->reserved1 || stm32hdr->reserved2)
116 return -1;
117 for (i = 0; i < (sizeof(stm32hdr->padding) / 4); i++) {
118 if (stm32hdr->padding[i] != 0)
119 return -1;
120 }
121
122 return 0;
123}
124
Marek Vasut076cdf72025-05-12 19:09:47 +0200125static int stm32image_verify_header_v2(unsigned char *ptr, int image_size,
126 struct image_tool_params *params)
127{
128 struct stm32_header_v2 *stm32hdr = (struct stm32_header_v2 *)ptr;
129 int i;
130
131 if (image_size < sizeof(struct stm32_header_v2))
132 return -1;
133 if (stm32hdr->magic_number != HEADER_MAGIC)
134 return -1;
135 if (stm32hdr->header_version[VER_MAJOR] != HEADER_VERSION_V2)
136 return -1;
137 if (stm32hdr->reserved1 || stm32hdr->reserved2)
138 return -1;
139 for (i = 0; i < (sizeof(stm32hdr->padding) / 4); i++) {
140 if (stm32hdr->padding[i] != 0)
141 return -1;
142 }
143
144 return 0;
145}
146
Pali Rohár0ed41e22023-03-29 21:25:54 +0200147static void stm32image_print_header(const void *ptr, struct image_tool_params *params)
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100148{
Marek Vasut076cdf72025-05-12 19:09:47 +0200149 struct stm32_header_v1 *stm32hdr_v1 = (struct stm32_header_v1 *)ptr;
150 struct stm32_header_v2 *stm32hdr_v2 = (struct stm32_header_v2 *)ptr;
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100151
152 printf("Image Type : STMicroelectronics STM32 V%d.%d\n",
Marek Vasut076cdf72025-05-12 19:09:47 +0200153 stm32hdr_v1->header_version[VER_MAJOR],
154 stm32hdr_v1->header_version[VER_MINOR]);
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100155 printf("Image Size : %lu bytes\n",
Marek Vasut076cdf72025-05-12 19:09:47 +0200156 (unsigned long)le32_to_cpu(stm32hdr_v1->image_length));
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100157 printf("Image Load : 0x%08x\n",
Marek Vasut076cdf72025-05-12 19:09:47 +0200158 le32_to_cpu(stm32hdr_v1->load_address));
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100159 printf("Entry Point : 0x%08x\n",
Marek Vasut076cdf72025-05-12 19:09:47 +0200160 le32_to_cpu(stm32hdr_v1->image_entry_point));
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100161 printf("Checksum : 0x%08x\n",
Marek Vasut076cdf72025-05-12 19:09:47 +0200162 le32_to_cpu(stm32hdr_v1->image_checksum));
163 switch (stm32hdr_v1->header_version[VER_MAJOR]) {
164 case HEADER_VERSION_V1:
165 printf("Option : 0x%08x\n",
166 le32_to_cpu(stm32hdr_v1->option_flags));
167 printf("BinaryType : 0x%08x\n",
168 le32_to_cpu(stm32hdr_v1->binary_type));
169 break;
170
171 case HEADER_VERSION_V2:
172 printf("Extension : 0x%08x\n",
173 le32_to_cpu(stm32hdr_v2->extension_flags));
174 break;
175
176 default:
177 printf("Incorrect header version\n");
178 }
179}
180
181static void stm32image_set_header_v1(void *ptr, struct stat *sbuf, int ifd,
182 struct image_tool_params *params)
183{
184 struct stm32_header_v1 *stm32hdr = (struct stm32_header_v1 *)ptr;
185
186 stm32hdr->magic_number = HEADER_MAGIC;
187 stm32hdr->version_number = cpu_to_le32(0);
188
189 stm32hdr->header_version[VER_MAJOR] = HEADER_VERSION_V1;
190 stm32hdr->option_flags = HEADER_DEFAULT_OPTION;
191 stm32hdr->ecdsa_algorithm = cpu_to_le32(1);
192 stm32hdr->binary_type = HEADER_TYPE_UBOOT;
193
194 stm32hdr->load_address = cpu_to_le32(params->addr);
195 stm32hdr->image_entry_point = cpu_to_le32(params->ep);
196 stm32hdr->image_length = cpu_to_le32((uint32_t)sbuf->st_size -
197 sizeof(*stm32hdr));
198 stm32hdr->image_checksum =
199 cpu_to_le32(stm32image_checksum(ptr, sbuf->st_size,
200 sizeof(*stm32hdr)));
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100201}
202
Marek Vasut076cdf72025-05-12 19:09:47 +0200203static void stm32image_set_header_v2(void *ptr, struct stat *sbuf, int ifd,
204 struct image_tool_params *params)
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100205{
Marek Vasut076cdf72025-05-12 19:09:47 +0200206 struct stm32_header_v2 *stm32hdr = (struct stm32_header_v2 *)ptr;
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100207
Marek Vasut076cdf72025-05-12 19:09:47 +0200208 stm32hdr->magic_number = HEADER_MAGIC;
209 stm32hdr->version_number = cpu_to_le32(0);
210
211 stm32hdr->header_version[VER_MAJOR] = HEADER_VERSION_V2;
212 stm32hdr->extension_flags =
213 cpu_to_le32(PADDING_HEADER_FLAG);
214 stm32hdr->extension_headers_length =
215 cpu_to_le32(PADDING_HEADER_LENGTH);
216 stm32hdr->extension_header_type =
217 cpu_to_le32(PADDING_HEADER_MAGIC);
218 stm32hdr->extension_header_length =
219 cpu_to_le32(PADDING_HEADER_LENGTH);
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100220
221 stm32hdr->load_address = cpu_to_le32(params->addr);
222 stm32hdr->image_entry_point = cpu_to_le32(params->ep);
223 stm32hdr->image_length = cpu_to_le32((uint32_t)sbuf->st_size -
Marek Vasut076cdf72025-05-12 19:09:47 +0200224 sizeof(*stm32hdr));
Antonio Borneoa2df6d62020-01-28 15:42:13 +0100225 stm32hdr->image_checksum =
Marek Vasut076cdf72025-05-12 19:09:47 +0200226 cpu_to_le32(stm32image_checksum(ptr, sbuf->st_size,
227 sizeof(*stm32hdr)));
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100228}
229
230/*
231 * stm32image parameters
232 */
233U_BOOT_IMAGE_TYPE(
234 stm32image,
235 "STMicroelectronics STM32MP Image support",
Marek Vasut076cdf72025-05-12 19:09:47 +0200236 sizeof(struct stm32_header_v1),
237 (void *)&stm32image_header_v1,
238 NULL,
239 stm32image_verify_header_v1,
240 stm32image_print_header,
241 stm32image_set_header_v1,
242 NULL,
243 stm32image_check_image_types_v1,
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100244 NULL,
Marek Vasut076cdf72025-05-12 19:09:47 +0200245 NULL
246);
247
248U_BOOT_IMAGE_TYPE(
249 stm32imagev2,
250 "STMicroelectronics STM32MP Image V2.0 support",
251 sizeof(struct stm32_header_v2),
252 (void *)&stm32image_header_v2,
253 NULL,
254 stm32image_verify_header_v2,
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100255 stm32image_print_header,
Marek Vasut076cdf72025-05-12 19:09:47 +0200256 stm32image_set_header_v2,
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100257 NULL,
Marek Vasut076cdf72025-05-12 19:09:47 +0200258 stm32image_check_image_types_v2,
Patrick Delaunaye6db5df2018-03-12 10:46:04 +0100259 NULL,
260 NULL
261);