blob: d6c10adc7eac7d2f5b934f84cf0f95bee7becb0f [file] [log] [blame]
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +00001/*
Peter Stuge45ae92ff2009-04-14 19:48:32 +00002 * cbfs-mkpayload
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +00003 *
4 * Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
Patrick Georgib7b56dd82009-09-14 13:29:27 +00005 * 2009 coresystems GmbH
6 * written by Patrick Georgi <patrick.georgi@coresystems.de>
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +00007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +000016 */
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
Werner Zeha7835c42018-06-15 14:02:18 +020021#include <commonlib/endian.h>
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +000022
Aaron Durbin54ef3062014-03-05 12:12:09 -060023#include "elfparsing.h"
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +000024#include "common.h"
Patrick Georgib7b56dd82009-09-14 13:29:27 +000025#include "cbfs.h"
Stefan Reinauer543a6822013-02-04 15:39:13 -080026#include "fv.h"
27#include "coff.h"
Patrick Rudolph7ee05ed2018-04-26 09:35:13 +020028#include "fdt.h"
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +000029
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -080030/* serialize the seg array into the buffer.
31 * The buffer is assumed to be large enough.
32 */
Ronald G. Minnich818f3692014-02-04 08:29:35 -080033void xdr_segs(struct buffer *output,
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -080034 struct cbfs_payload_segment *segs, int nseg)
35{
36 struct buffer outheader;
37 int i;
38
39 outheader.data = output->data;
40 outheader.size = 0;
41
42 for(i = 0; i < nseg; i++){
43 xdr_be.put32(&outheader, segs[i].type);
44 xdr_be.put32(&outheader, segs[i].compression);
45 xdr_be.put32(&outheader, segs[i].offset);
46 xdr_be.put64(&outheader, segs[i].load_addr);
47 xdr_be.put32(&outheader, segs[i].len);
48 xdr_be.put32(&outheader, segs[i].mem_len);
49 }
50}
Aaron Durbinca630272014-08-05 10:48:20 -050051
52void xdr_get_seg(struct cbfs_payload_segment *out,
53 struct cbfs_payload_segment *in)
54{
55 struct buffer inheader;
56
57 inheader.data = (void *)in;
58 inheader.size = sizeof(*in);
59
60 out->type = xdr_be.get32(&inheader);
61 out->compression = xdr_be.get32(&inheader);
62 out->offset = xdr_be.get32(&inheader);
63 out->load_addr = xdr_be.get64(&inheader);
64 out->len = xdr_be.get32(&inheader);
65 out->mem_len = xdr_be.get32(&inheader);
66}
67
Sol Boucher0e539312015-03-05 15:38:03 -080068int parse_elf_to_payload(const struct buffer *input, struct buffer *output,
Sol Boucher6310ccc2015-05-07 21:12:28 -070069 enum comp_algo algo)
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +000070{
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -080071 Elf64_Phdr *phdr;
72 Elf64_Ehdr ehdr;
73 Elf64_Shdr *shdr;
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +000074 char *header;
75 char *strtab;
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +000076 int headers;
77 int segments = 1;
78 int isize = 0, osize = 0;
79 int doffset = 0;
Patrick Georgi96990a22014-09-29 10:08:35 +020080 struct cbfs_payload_segment *segs = NULL;
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +000081 int i;
Patrick Georgi96990a22014-09-29 10:08:35 +020082 int ret = 0;
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +000083
Patrick Georgib7b56dd82009-09-14 13:29:27 +000084 comp_func_ptr compress = compression_function(algo);
85 if (!compress)
86 return -1;
87
Sol Boucher0e539312015-03-05 15:38:03 -080088 if (elf_headers(input, &ehdr, &phdr, &shdr) < 0)
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -080089 return -1;
90
Hung-Te Linc13e4bf2013-01-29 15:22:11 +080091 DEBUG("start: parse_elf_to_payload\n");
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -080092 headers = ehdr.e_phnum;
93 header = input->data;
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +000094
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -080095 strtab = &header[shdr[ehdr.e_shstrndx].sh_offset];
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +000096
97 /* Count the number of headers - look for the .notes.pinfo
98 * section */
99
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800100 for (i = 0; i < ehdr.e_shnum; i++) {
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000101 char *name;
102
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800103 if (i == ehdr.e_shstrndx)
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000104 continue;
105
106 if (shdr[i].sh_size == 0)
107 continue;
108
109 name = (char *)(strtab + shdr[i].sh_name);
110
Ronald G. Minnich5a1af7b2009-09-17 15:35:08 +0000111 if (!strcmp(name, ".note.pinfo")) {
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000112 segments++;
Ronald G. Minnich5a1af7b2009-09-17 15:35:08 +0000113 isize += (unsigned int)shdr[i].sh_size;
114 }
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000115 }
116
117 /* Now, regular headers - we only care about PT_LOAD headers,
118 * because thats what we're actually going to load
119 */
120
121 for (i = 0; i < headers; i++) {
122 if (phdr[i].p_type != PT_LOAD)
123 continue;
124
125 /* Empty segments are never interesting */
126 if (phdr[i].p_memsz == 0)
127 continue;
128
129 isize += phdr[i].p_filesz;
130
131 segments++;
132 }
Joel Kitchinga302e7f2018-07-19 07:36:38 +0800133 /* Allocate and initialize the segment header array */
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800134 segs = calloc(segments, sizeof(*segs));
Patrick Georgi96990a22014-09-29 10:08:35 +0200135 if (segs == NULL) {
136 ret = -1;
137 goto out;
138 }
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000139 /* Allocate a block of memory to store the data in */
Hung-Te Linc13e4bf2013-01-29 15:22:11 +0800140 if (buffer_create(output, (segments * sizeof(*segs)) + isize,
Patrick Georgi96990a22014-09-29 10:08:35 +0200141 input->name) != 0) {
142 ret = -1;
143 goto out;
144 }
Hung-Te Linc13e4bf2013-01-29 15:22:11 +0800145 memset(output->data, 0, output->size);
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000146
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800147 doffset = (segments * sizeof(*segs));
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000148
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800149 /* set up for output marshaling. This is a bit
150 * tricky as we are marshaling the headers at the front,
151 * and the data starting after the headers. We need to convert
152 * the headers to the right format but the data
153 * passes through unchanged. Unlike most XDR code,
154 * we are doing these two concurrently. The doffset is
155 * used to compute the address for the raw data, and the
156 * outheader is used to marshal the headers. To make it simpler
157 * for The Reader, we set up the headers in a separate array,
158 * then marshal them all at once to the output.
159 */
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000160 segments = 0;
161
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800162 for (i = 0; i < ehdr.e_shnum; i++) {
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000163 char *name;
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800164 if (i == ehdr.e_shstrndx)
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000165 continue;
166
167 if (shdr[i].sh_size == 0)
168 continue;
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000169 name = (char *)(strtab + shdr[i].sh_name);
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000170 if (!strcmp(name, ".note.pinfo")) {
171 segs[segments].type = PAYLOAD_SEGMENT_PARAMS;
172 segs[segments].load_addr = 0;
173 segs[segments].len = (unsigned int)shdr[i].sh_size;
174 segs[segments].offset = doffset;
175
Hung-Te Linc13e4bf2013-01-29 15:22:11 +0800176 memcpy((unsigned long *)(output->data + doffset),
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000177 &header[shdr[i].sh_offset], shdr[i].sh_size);
178
179 doffset += segs[segments].len;
180 osize += segs[segments].len;
181
182 segments++;
183 }
184 }
185
186 for (i = 0; i < headers; i++) {
187 if (phdr[i].p_type != PT_LOAD)
188 continue;
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000189 if (phdr[i].p_memsz == 0)
190 continue;
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000191 if (phdr[i].p_filesz == 0) {
192 segs[segments].type = PAYLOAD_SEGMENT_BSS;
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800193 segs[segments].load_addr = phdr[i].p_paddr;
194 segs[segments].mem_len = phdr[i].p_memsz;
195 segs[segments].offset = doffset;
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000196
197 segments++;
198 continue;
199 }
200
Stefan Reinauer51f6a202012-01-11 12:40:14 -0800201 if (phdr[i].p_flags & PF_X)
202 segs[segments].type = PAYLOAD_SEGMENT_CODE;
203 else
204 segs[segments].type = PAYLOAD_SEGMENT_DATA;
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800205 segs[segments].load_addr = phdr[i].p_paddr;
206 segs[segments].mem_len = phdr[i].p_memsz;
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800207 segs[segments].offset = doffset;
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000208
Gabe Black845aa142014-02-21 01:01:06 -0800209 /* If the compression failed or made the section is larger,
210 use the original stuff */
211
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000212 int len;
Gabe Blackdbd006b2014-02-20 23:38:49 -0800213 if (compress((char *)&header[phdr[i].p_offset],
Gabe Black845aa142014-02-21 01:01:06 -0800214 phdr[i].p_filesz, output->data + doffset, &len) ||
215 (unsigned int)len > phdr[i].p_filesz) {
216 WARN("Compression failed or would make the data bigger "
217 "- disabled.\n");
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000218 segs[segments].compression = 0;
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800219 segs[segments].len = phdr[i].p_filesz;
Hung-Te Linc13e4bf2013-01-29 15:22:11 +0800220 memcpy(output->data + doffset,
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000221 &header[phdr[i].p_offset], phdr[i].p_filesz);
Gabe Black845aa142014-02-21 01:01:06 -0800222 } else {
223 segs[segments].compression = algo;
224 segs[segments].len = len;
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000225 }
226
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800227 doffset += segs[segments].len;
228 osize += segs[segments].len;
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000229
230 segments++;
231 }
232
233 segs[segments].type = PAYLOAD_SEGMENT_ENTRY;
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800234 segs[segments++].load_addr = ehdr.e_entry;
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000235
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800236 output->size = (segments * sizeof(*segs)) + osize;
237 xdr_segs(output, segs, segments);
Patrick Georgi96990a22014-09-29 10:08:35 +0200238
239out:
240 if (segs) free(segs);
241 if (shdr) free(shdr);
242 if (phdr) free(phdr);
243 return ret;
Ronald G. Minnich5d01ec02009-03-31 11:57:36 +0000244}
Hung-Te Lin05dccae2013-01-28 15:04:30 +0800245
Hung-Te Linc13e4bf2013-01-29 15:22:11 +0800246int parse_flat_binary_to_payload(const struct buffer *input,
247 struct buffer *output,
Hung-Te Lin05dccae2013-01-28 15:04:30 +0800248 uint32_t loadaddress,
249 uint32_t entrypoint,
Sol Boucher6310ccc2015-05-07 21:12:28 -0700250 enum comp_algo algo)
Hung-Te Lin05dccae2013-01-28 15:04:30 +0800251{
252 comp_func_ptr compress;
Patrick Georgi71955a52018-07-19 17:33:57 +0200253 struct cbfs_payload_segment segs[2] = { {0} };
Hung-Te Lin05dccae2013-01-28 15:04:30 +0800254 int doffset, len = 0;
255
256 compress = compression_function(algo);
257 if (!compress)
258 return -1;
259
260 DEBUG("start: parse_flat_binary_to_payload\n");
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800261 if (buffer_create(output, (sizeof(segs) + input->size),
Hung-Te Linc13e4bf2013-01-29 15:22:11 +0800262 input->name) != 0)
Hung-Te Lin05dccae2013-01-28 15:04:30 +0800263 return -1;
Hung-Te Linc13e4bf2013-01-29 15:22:11 +0800264 memset(output->data, 0, output->size);
Hung-Te Lin05dccae2013-01-28 15:04:30 +0800265
Hung-Te Lin05dccae2013-01-28 15:04:30 +0800266 doffset = (2 * sizeof(*segs));
267
268 /* Prepare code segment */
269 segs[0].type = PAYLOAD_SEGMENT_CODE;
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800270 segs[0].load_addr = loadaddress;
271 segs[0].mem_len = input->size;
272 segs[0].offset = doffset;
Hung-Te Lin05dccae2013-01-28 15:04:30 +0800273
Gabe Black845aa142014-02-21 01:01:06 -0800274 if (!compress(input->data, input->size, output->data + doffset, &len) &&
275 (unsigned int)len < input->size) {
276 segs[0].compression = algo;
277 segs[0].len = len;
278 } else {
279 WARN("Compression failed or would make the data bigger "
280 "- disabled.\n");
Hung-Te Lin05dccae2013-01-28 15:04:30 +0800281 segs[0].compression = 0;
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800282 segs[0].len = input->size;
Hung-Te Linc13e4bf2013-01-29 15:22:11 +0800283 memcpy(output->data + doffset, input->data, input->size);
Hung-Te Lin05dccae2013-01-28 15:04:30 +0800284 }
285
286 /* prepare entry point segment */
287 segs[1].type = PAYLOAD_SEGMENT_ENTRY;
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800288 segs[1].load_addr = entrypoint;
289 output->size = doffset + segs[0].len;
290 xdr_segs(output, segs, 2);
Hung-Te Linc13e4bf2013-01-29 15:22:11 +0800291 return 0;
Hung-Te Lin05dccae2013-01-28 15:04:30 +0800292}
Stefan Reinauer543a6822013-02-04 15:39:13 -0800293
Sol Boucher6310ccc2015-05-07 21:12:28 -0700294int parse_fv_to_payload(const struct buffer *input, struct buffer *output,
295 enum comp_algo algo)
Stefan Reinauer543a6822013-02-04 15:39:13 -0800296{
297 comp_func_ptr compress;
Patrick Georgi71955a52018-07-19 17:33:57 +0200298 struct cbfs_payload_segment segs[2] = { {0} };
Stefan Reinauer543a6822013-02-04 15:39:13 -0800299 int doffset, len = 0;
300 firmware_volume_header_t *fv;
301 ffs_file_header_t *fh;
302 common_section_header_t *cs;
303 dos_header_t *dh;
304 coff_header_t *ch;
Stefan Reinauer543a6822013-02-04 15:39:13 -0800305 int dh_offset;
306
Stefan Reinauere8764182013-02-05 13:46:49 -0800307 uint32_t loadaddress = 0;
308 uint32_t entrypoint = 0;
Stefan Reinauer543a6822013-02-04 15:39:13 -0800309
310 compress = compression_function(algo);
311 if (!compress)
312 return -1;
313
314 DEBUG("start: parse_fv_to_payload\n");
315
316 fv = (firmware_volume_header_t *)input->data;
317 if (fv->signature != FV_SIGNATURE) {
318 INFO("Not a UEFI firmware volume.\n");
319 return -1;
320 }
321
322 fh = (ffs_file_header_t *)(input->data + fv->header_length);
Patrick Georgi46102472013-02-09 13:26:19 +0100323 while (fh->file_type == FILETYPE_PAD) {
324 unsigned long offset = (fh->size[2] << 16) | (fh->size[1] << 8) | fh->size[0];
Patrick Georgi50bda052017-07-05 13:30:37 +0200325 DEBUG("skipping %lu bytes of FV padding\n", offset);
Sol Boucher0e539312015-03-05 15:38:03 -0800326 fh = (ffs_file_header_t *)(((uintptr_t)fh) + offset);
Patrick Georgi46102472013-02-09 13:26:19 +0100327 }
Stefan Reinauer543a6822013-02-04 15:39:13 -0800328 if (fh->file_type != FILETYPE_SEC) {
329 ERROR("Not a usable UEFI firmware volume.\n");
Stefan Reinauere8764182013-02-05 13:46:49 -0800330 INFO("First file in first FV not a SEC core.\n");
Stefan Reinauer543a6822013-02-04 15:39:13 -0800331 return -1;
332 }
333
334 cs = (common_section_header_t *)&fh[1];
Patrick Georgi46102472013-02-09 13:26:19 +0100335 while (cs->section_type == SECTION_RAW) {
336 unsigned long offset = (cs->size[2] << 16) | (cs->size[1] << 8) | cs->size[0];
Patrick Georgi50bda052017-07-05 13:30:37 +0200337 DEBUG("skipping %lu bytes of section padding\n", offset);
Sol Boucher0e539312015-03-05 15:38:03 -0800338 cs = (common_section_header_t *)(((uintptr_t)cs) + offset);
Patrick Georgi46102472013-02-09 13:26:19 +0100339 }
Stefan Reinauer543a6822013-02-04 15:39:13 -0800340 if (cs->section_type != SECTION_PE32) {
341 ERROR("Not a usable UEFI firmware volume.\n");
Stefan Reinauere8764182013-02-05 13:46:49 -0800342 INFO("Section type not PE32.\n");
Stefan Reinauer543a6822013-02-04 15:39:13 -0800343 return -1;
344 }
345
346 dh = (dos_header_t *)&cs[1];
Stefan Reinauere8764182013-02-05 13:46:49 -0800347 if (dh->signature != DOS_MAGIC) {
Stefan Reinauer543a6822013-02-04 15:39:13 -0800348 ERROR("Not a usable UEFI firmware volume.\n");
Stefan Reinauere8764182013-02-05 13:46:49 -0800349 INFO("DOS header signature wrong.\n");
Stefan Reinauer543a6822013-02-04 15:39:13 -0800350 return -1;
351 }
352
353 dh_offset = (unsigned long)dh - (unsigned long)input->data;
354 DEBUG("dos header offset = %x\n", dh_offset);
355
Sol Boucher0e539312015-03-05 15:38:03 -0800356 ch = (coff_header_t *)(((uintptr_t)dh)+dh->e_lfanew);
Stefan Reinauere8764182013-02-05 13:46:49 -0800357
358 if (ch->machine == MACHINE_TYPE_X86) {
359 pe_opt_header_32_t *ph;
360 ph = (pe_opt_header_32_t *)&ch[1];
361 if (ph->signature != PE_HDR_32_MAGIC) {
362 WARN("PE header signature incorrect.\n");
363 return -1;
364 }
365 DEBUG("image base %x\n", ph->image_addr);
366 DEBUG("entry point %x\n", ph->entry_point);
367
368 loadaddress = ph->image_addr - dh_offset;
369 entrypoint = ph->image_addr + ph->entry_point;
370 } else if (ch->machine == MACHINE_TYPE_X64) {
371 pe_opt_header_64_t *ph;
372 ph = (pe_opt_header_64_t *)&ch[1];
373 if (ph->signature != PE_HDR_64_MAGIC) {
374 WARN("PE header signature incorrect.\n");
375 return -1;
376 }
377 DEBUG("image base %lx\n", (unsigned long)ph->image_addr);
378 DEBUG("entry point %x\n", ph->entry_point);
379
380 loadaddress = ph->image_addr - dh_offset;
381 entrypoint = ph->image_addr + ph->entry_point;
382 } else {
383 ERROR("Machine type not x86 or x64.\n");
Stefan Reinauer543a6822013-02-04 15:39:13 -0800384 return -1;
385 }
386
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800387 if (buffer_create(output, (sizeof(segs) + input->size),
Stefan Reinauer543a6822013-02-04 15:39:13 -0800388 input->name) != 0)
389 return -1;
390
391 memset(output->data, 0, output->size);
392
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800393 doffset = (sizeof(segs));
Stefan Reinauer543a6822013-02-04 15:39:13 -0800394
395 /* Prepare code segment */
396 segs[0].type = PAYLOAD_SEGMENT_CODE;
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800397 segs[0].load_addr = loadaddress;
398 segs[0].mem_len = input->size;
399 segs[0].offset = doffset;
Stefan Reinauer543a6822013-02-04 15:39:13 -0800400
Gabe Black845aa142014-02-21 01:01:06 -0800401 if (!compress(input->data, input->size, output->data + doffset, &len) &&
402 (unsigned int)len < input->size) {
403 segs[0].compression = algo;
404 segs[0].len = len;
405 } else {
406 WARN("Compression failed or would make the data bigger "
407 "- disabled.\n");
Stefan Reinauer543a6822013-02-04 15:39:13 -0800408 segs[0].compression = 0;
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800409 segs[0].len = input->size;
Stefan Reinauer543a6822013-02-04 15:39:13 -0800410 memcpy(output->data + doffset, input->data, input->size);
411 }
412
413 /* prepare entry point segment */
414 segs[1].type = PAYLOAD_SEGMENT_ENTRY;
Ronald G. Minnicha8a133d2013-12-30 13:16:18 -0800415 segs[1].load_addr = entrypoint;
416 output->size = doffset + segs[0].len;
417 xdr_segs(output, segs, 2);
Stefan Reinauer543a6822013-02-04 15:39:13 -0800418 return 0;
419
420}
Patrick Rudolph7ee05ed2018-04-26 09:35:13 +0200421
422int parse_fit_to_payload(const struct buffer *input, struct buffer *output,
423 enum comp_algo algo)
424{
425 struct fdt_header *fdt_h;
426
427 DEBUG("start: parse_fit_to_payload\n");
428
429 fdt_h = buffer_get(input);
Werner Zeha7835c42018-06-15 14:02:18 +0200430 if (read_be32(&fdt_h->magic) != FDT_HEADER_MAGIC) {
Patrick Rudolph7ee05ed2018-04-26 09:35:13 +0200431 INFO("Not a FIT payload.\n");
432 return -1;
433 }
434
435 /**
436 * For developers:
437 * Compress the kernel binary you're sourcing in your its-script
438 * manually with LZ4 or LZMA and add 'compression = "lz4"' or "lzma" to
439 * the kernel@1 node in the its-script before assembling the image with
440 * mkimage.
441 */
442 if (algo != CBFS_COMPRESS_NONE) {
443 ERROR("FIT images don't support whole-image compression,"
444 " compress the kernel component instead!\n")
445 return -1;
446 }
447
448 if (buffer_create(output, buffer_size(input), input->name) != 0)
449 return -1;
450
451 memcpy(buffer_get(output), buffer_get(input), buffer_size(input));
452
453 DEBUG("done\n");
454
455 return 0;
456}