]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/dpdk/drivers/net/sfc/base/ef10_image.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / dpdk / drivers / net / sfc / base / ef10_image.c
CommitLineData
11fdf7f2
TL
1/* SPDX-License-Identifier: BSD-3-Clause
2 *
3 * Copyright (c) 2017-2018 Solarflare Communications Inc.
4 * All rights reserved.
5 */
6
7#include "efx.h"
8#include "efx_impl.h"
9
10#if EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
11
12#if EFSYS_OPT_IMAGE_LAYOUT
13
14/*
15 * Utility routines to support limited parsing of ASN.1 tags. This is not a
16 * general purpose ASN.1 parser, but is sufficient to locate the required
17 * objects in a signed image with CMS headers.
18 */
19
20/* DER encodings for ASN.1 tags (see ITU-T X.690) */
21#define ASN1_TAG_INTEGER (0x02)
22#define ASN1_TAG_OCTET_STRING (0x04)
23#define ASN1_TAG_OBJ_ID (0x06)
24#define ASN1_TAG_SEQUENCE (0x30)
25#define ASN1_TAG_SET (0x31)
26
27#define ASN1_TAG_IS_PRIM(tag) ((tag & 0x20) == 0)
28
29#define ASN1_TAG_PRIM_CONTEXT(n) (0x80 + (n))
30#define ASN1_TAG_CONS_CONTEXT(n) (0xA0 + (n))
31
32typedef struct efx_asn1_cursor_s {
33 uint8_t *buffer;
34 uint32_t length;
35
36 uint8_t tag;
37 uint32_t hdr_size;
38 uint32_t val_size;
39} efx_asn1_cursor_t;
40
41
42/* Parse header of DER encoded ASN.1 TLV and match tag */
43static __checkReturn efx_rc_t
44efx_asn1_parse_header_match_tag(
45 __inout efx_asn1_cursor_t *cursor,
46 __in uint8_t tag)
47{
48 efx_rc_t rc;
49
50 if (cursor == NULL || cursor->buffer == NULL || cursor->length < 2) {
51 rc = EINVAL;
52 goto fail1;
53 }
54
55 cursor->tag = cursor->buffer[0];
56 if (cursor->tag != tag) {
57 /* Tag not matched */
58 rc = ENOENT;
59 goto fail2;
60 }
61
62 if ((cursor->tag & 0x1F) == 0x1F) {
63 /* Long tag format not used in CMS syntax */
64 rc = EINVAL;
65 goto fail3;
66 }
67
68 if ((cursor->buffer[1] & 0x80) == 0) {
69 /* Short form: length is 0..127 */
70 cursor->hdr_size = 2;
71 cursor->val_size = cursor->buffer[1];
72 } else {
73 /* Long form: length encoded as [0x80+nbytes][length bytes] */
74 uint32_t nbytes = cursor->buffer[1] & 0x7F;
75 uint32_t offset;
76
77 if (nbytes == 0) {
78 /* Indefinite length not allowed in DER encoding */
79 rc = EINVAL;
80 goto fail4;
81 }
82 if (2 + nbytes > cursor->length) {
83 /* Header length overflows image buffer */
84 rc = EINVAL;
85 goto fail6;
86 }
87 if (nbytes > sizeof (uint32_t)) {
88 /* Length encoding too big */
89 rc = E2BIG;
90 goto fail5;
91 }
92 cursor->hdr_size = 2 + nbytes;
93 cursor->val_size = 0;
94 for (offset = 2; offset < cursor->hdr_size; offset++) {
95 cursor->val_size =
96 (cursor->val_size << 8) | cursor->buffer[offset];
97 }
98 }
99
100 if ((cursor->hdr_size + cursor->val_size) > cursor->length) {
101 /* Length overflows image buffer */
102 rc = E2BIG;
103 goto fail7;
104 }
105
106 return (0);
107
108fail7:
109 EFSYS_PROBE(fail7);
110fail6:
111 EFSYS_PROBE(fail6);
112fail5:
113 EFSYS_PROBE(fail5);
114fail4:
115 EFSYS_PROBE(fail4);
116fail3:
117 EFSYS_PROBE(fail3);
118fail2:
119 EFSYS_PROBE(fail2);
120fail1:
121 EFSYS_PROBE1(fail1, efx_rc_t, rc);
122
123 return (rc);
124}
125
126/* Enter nested ASN.1 TLV (contained in value of current TLV) */
127static __checkReturn efx_rc_t
128efx_asn1_enter_tag(
129 __inout efx_asn1_cursor_t *cursor,
130 __in uint8_t tag)
131{
132 efx_rc_t rc;
133
134 if (cursor == NULL) {
135 rc = EINVAL;
136 goto fail1;
137 }
138
139 if (ASN1_TAG_IS_PRIM(tag)) {
140 /* Cannot enter a primitive tag */
141 rc = ENOTSUP;
142 goto fail2;
143 }
144 rc = efx_asn1_parse_header_match_tag(cursor, tag);
145 if (rc != 0) {
146 /* Invalid TLV or wrong tag */
147 goto fail3;
148 }
149
150 /* Limit cursor range to nested TLV */
151 cursor->buffer += cursor->hdr_size;
152 cursor->length = cursor->val_size;
153
154 return (0);
155
156fail3:
157 EFSYS_PROBE(fail3);
158fail2:
159 EFSYS_PROBE(fail2);
160fail1:
161 EFSYS_PROBE1(fail1, efx_rc_t, rc);
162
163 return (rc);
164}
165
166/*
167 * Check that the current ASN.1 TLV matches the given tag and value.
168 * Advance cursor to next TLV on a successful match.
169 */
170static __checkReturn efx_rc_t
171efx_asn1_match_tag_value(
172 __inout efx_asn1_cursor_t *cursor,
173 __in uint8_t tag,
174 __in const void *valp,
175 __in uint32_t val_size)
176{
177 efx_rc_t rc;
178
179 if (cursor == NULL) {
180 rc = EINVAL;
181 goto fail1;
182 }
183 rc = efx_asn1_parse_header_match_tag(cursor, tag);
184 if (rc != 0) {
185 /* Invalid TLV or wrong tag */
186 goto fail2;
187 }
188 if (cursor->val_size != val_size) {
189 /* Value size is different */
190 rc = EINVAL;
191 goto fail3;
192 }
193 if (memcmp(cursor->buffer + cursor->hdr_size, valp, val_size) != 0) {
194 /* Value content is different */
195 rc = EINVAL;
196 goto fail4;
197 }
198 cursor->buffer += cursor->hdr_size + cursor->val_size;
199 cursor->length -= cursor->hdr_size + cursor->val_size;
200
201 return (0);
202
203fail4:
204 EFSYS_PROBE(fail4);
205fail3:
206 EFSYS_PROBE(fail3);
207fail2:
208 EFSYS_PROBE(fail2);
209fail1:
210 EFSYS_PROBE1(fail1, efx_rc_t, rc);
211
212 return (rc);
213}
214
215/* Advance cursor to next TLV */
216static __checkReturn efx_rc_t
217efx_asn1_skip_tag(
218 __inout efx_asn1_cursor_t *cursor,
219 __in uint8_t tag)
220{
221 efx_rc_t rc;
222
223 if (cursor == NULL) {
224 rc = EINVAL;
225 goto fail1;
226 }
227
228 rc = efx_asn1_parse_header_match_tag(cursor, tag);
229 if (rc != 0) {
230 /* Invalid TLV or wrong tag */
231 goto fail2;
232 }
233 cursor->buffer += cursor->hdr_size + cursor->val_size;
234 cursor->length -= cursor->hdr_size + cursor->val_size;
235
236 return (0);
237
238fail2:
239 EFSYS_PROBE(fail2);
240fail1:
241 EFSYS_PROBE1(fail1, efx_rc_t, rc);
242
243 return (rc);
244}
245
246/* Return pointer to value octets and value size from current TLV */
247static __checkReturn efx_rc_t
248efx_asn1_get_tag_value(
249 __inout efx_asn1_cursor_t *cursor,
250 __in uint8_t tag,
251 __out uint8_t **valp,
252 __out uint32_t *val_sizep)
253{
254 efx_rc_t rc;
255
256 if (cursor == NULL || valp == NULL || val_sizep == NULL) {
257 rc = EINVAL;
258 goto fail1;
259 }
260
261 rc = efx_asn1_parse_header_match_tag(cursor, tag);
262 if (rc != 0) {
263 /* Invalid TLV or wrong tag */
264 goto fail2;
265 }
266 *valp = cursor->buffer + cursor->hdr_size;
267 *val_sizep = cursor->val_size;
268
269 return (0);
270
271fail2:
272 EFSYS_PROBE(fail2);
273fail1:
274 EFSYS_PROBE1(fail1, efx_rc_t, rc);
275
276 return (rc);
277}
278
279
280/*
281 * Utility routines for parsing CMS headers (see RFC2315, PKCS#7)
282 */
283
284/* OID 1.2.840.113549.1.7.2 */
285static const uint8_t PKCS7_SignedData[] =
286{ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02 };
287
288/* OID 1.2.840.113549.1.7.1 */
289static const uint8_t PKCS7_Data[] =
290{ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 };
291
292/* SignedData structure version */
293static const uint8_t SignedData_Version[] =
294{ 0x03 };
295
296/*
297 * Check for a valid image in signed image format. This uses CMS syntax
298 * (see RFC2315, PKCS#7) to provide signatures, and certificates required
299 * to validate the signatures. The encapsulated content is in unsigned image
300 * format (reflash header, image code, trailer checksum).
301 */
302static __checkReturn efx_rc_t
303efx_check_signed_image_header(
304 __in void *bufferp,
305 __in uint32_t buffer_size,
306 __out uint32_t *content_offsetp,
307 __out uint32_t *content_lengthp)
308{
309 efx_asn1_cursor_t cursor;
310 uint8_t *valp;
311 uint32_t val_size;
312 efx_rc_t rc;
313
314 if (content_offsetp == NULL || content_lengthp == NULL) {
315 rc = EINVAL;
316 goto fail1;
317 }
318 cursor.buffer = (uint8_t *)bufferp;
319 cursor.length = buffer_size;
320
321 /* ContextInfo */
322 rc = efx_asn1_enter_tag(&cursor, ASN1_TAG_SEQUENCE);
323 if (rc != 0)
324 goto fail2;
325
326 /* ContextInfo.contentType */
327 rc = efx_asn1_match_tag_value(&cursor, ASN1_TAG_OBJ_ID,
328 PKCS7_SignedData, sizeof (PKCS7_SignedData));
329 if (rc != 0)
330 goto fail3;
331
332 /* ContextInfo.content */
333 rc = efx_asn1_enter_tag(&cursor, ASN1_TAG_CONS_CONTEXT(0));
334 if (rc != 0)
335 goto fail4;
336
337 /* SignedData */
338 rc = efx_asn1_enter_tag(&cursor, ASN1_TAG_SEQUENCE);
339 if (rc != 0)
340 goto fail5;
341
342 /* SignedData.version */
343 rc = efx_asn1_match_tag_value(&cursor, ASN1_TAG_INTEGER,
344 SignedData_Version, sizeof (SignedData_Version));
345 if (rc != 0)
346 goto fail6;
347
348 /* SignedData.digestAlgorithms */
349 rc = efx_asn1_skip_tag(&cursor, ASN1_TAG_SET);
350 if (rc != 0)
351 goto fail7;
352
353 /* SignedData.encapContentInfo */
354 rc = efx_asn1_enter_tag(&cursor, ASN1_TAG_SEQUENCE);
355 if (rc != 0)
356 goto fail8;
357
358 /* SignedData.encapContentInfo.econtentType */
359 rc = efx_asn1_match_tag_value(&cursor, ASN1_TAG_OBJ_ID,
360 PKCS7_Data, sizeof (PKCS7_Data));
361 if (rc != 0)
362 goto fail9;
363
364 /* SignedData.encapContentInfo.econtent */
365 rc = efx_asn1_enter_tag(&cursor, ASN1_TAG_CONS_CONTEXT(0));
366 if (rc != 0)
367 goto fail10;
368
369 /*
370 * The octet string contains the image header, image code bytes and
371 * image trailer CRC (same as unsigned image layout).
372 */
373 valp = NULL;
374 val_size = 0;
375 rc = efx_asn1_get_tag_value(&cursor, ASN1_TAG_OCTET_STRING,
376 &valp, &val_size);
377 if (rc != 0)
378 goto fail11;
379
380 if ((valp == NULL) || (val_size == 0)) {
381 rc = EINVAL;
382 goto fail12;
383 }
384 if (valp < (uint8_t *)bufferp) {
385 rc = EINVAL;
386 goto fail13;
387 }
388 if ((valp + val_size) > ((uint8_t *)bufferp + buffer_size)) {
389 rc = EINVAL;
390 goto fail14;
391 }
392
393 *content_offsetp = (uint32_t)(valp - (uint8_t *)bufferp);
394 *content_lengthp = val_size;
395
396 return (0);
397
398fail14:
399 EFSYS_PROBE(fail14);
400fail13:
401 EFSYS_PROBE(fail13);
402fail12:
403 EFSYS_PROBE(fail12);
404fail11:
405 EFSYS_PROBE(fail11);
406fail10:
407 EFSYS_PROBE(fail10);
408fail9:
409 EFSYS_PROBE(fail9);
410fail8:
411 EFSYS_PROBE(fail8);
412fail7:
413 EFSYS_PROBE(fail7);
414fail6:
415 EFSYS_PROBE(fail6);
416fail5:
417 EFSYS_PROBE(fail5);
418fail4:
419 EFSYS_PROBE(fail4);
420fail3:
421 EFSYS_PROBE(fail3);
422fail2:
423 EFSYS_PROBE(fail2);
424fail1:
425 EFSYS_PROBE1(fail1, efx_rc_t, rc);
426
427 return (rc);
428}
429
430static __checkReturn efx_rc_t
431efx_check_unsigned_image(
432 __in void *bufferp,
433 __in uint32_t buffer_size)
434{
435 efx_image_header_t *header;
436 efx_image_trailer_t *trailer;
437 uint32_t crc;
438 efx_rc_t rc;
439
440 EFX_STATIC_ASSERT(sizeof (*header) == EFX_IMAGE_HEADER_SIZE);
441 EFX_STATIC_ASSERT(sizeof (*trailer) == EFX_IMAGE_TRAILER_SIZE);
442
443 /* Must have at least enough space for required image header fields */
444 if (buffer_size < (EFX_FIELD_OFFSET(efx_image_header_t, eih_size) +
445 sizeof (header->eih_size))) {
446 rc = ENOSPC;
447 goto fail1;
448 }
449 header = (efx_image_header_t *)bufferp;
450
451 if (header->eih_magic != EFX_IMAGE_HEADER_MAGIC) {
452 rc = EINVAL;
453 goto fail2;
454 }
455
456 /*
457 * Check image header version is same or higher than lowest required
458 * version.
459 */
460 if (header->eih_version < EFX_IMAGE_HEADER_VERSION) {
461 rc = EINVAL;
462 goto fail3;
463 }
464
465 /* Buffer must have space for image header, code and image trailer. */
466 if (buffer_size < (header->eih_size + header->eih_code_size +
467 EFX_IMAGE_TRAILER_SIZE)) {
468 rc = ENOSPC;
469 goto fail4;
470 }
471
472 /* Check CRC from image buffer matches computed CRC. */
473 trailer = (efx_image_trailer_t *)((uint8_t *)header +
474 header->eih_size + header->eih_code_size);
475
476 crc = efx_crc32_calculate(0, (uint8_t *)header,
477 (header->eih_size + header->eih_code_size));
478
479 if (trailer->eit_crc != crc) {
480 rc = EINVAL;
481 goto fail5;
482 }
483
484 return (0);
485
486fail5:
487 EFSYS_PROBE(fail5);
488fail4:
489 EFSYS_PROBE(fail4);
490fail3:
491 EFSYS_PROBE(fail3);
492fail2:
493 EFSYS_PROBE(fail2);
494fail1:
495 EFSYS_PROBE1(fail1, efx_rc_t, rc);
496
497 return (rc);
498}
499
500 __checkReturn efx_rc_t
501efx_check_reflash_image(
502 __in void *bufferp,
503 __in uint32_t buffer_size,
504 __out efx_image_info_t *infop)
505{
506 efx_image_format_t format = EFX_IMAGE_FORMAT_NO_IMAGE;
507 uint32_t image_offset;
508 uint32_t image_size;
509 void *imagep;
510 efx_rc_t rc;
511
512
513 EFSYS_ASSERT(infop != NULL);
514 if (infop == NULL) {
515 rc = EINVAL;
516 goto fail1;
517 }
518 memset(infop, 0, sizeof (*infop));
519
520 if (bufferp == NULL || buffer_size == 0) {
521 rc = EINVAL;
522 goto fail2;
523 }
524
525 /*
526 * Check if the buffer contains an image in signed format, and if so,
527 * locate the image header.
528 */
529 rc = efx_check_signed_image_header(bufferp, buffer_size,
530 &image_offset, &image_size);
531 if (rc == 0) {
532 /*
533 * Buffer holds signed image format. Check that the encapsulated
534 * content is in unsigned image format.
535 */
536 format = EFX_IMAGE_FORMAT_SIGNED;
537 } else {
538 /* Check if the buffer holds image in unsigned image format */
539 format = EFX_IMAGE_FORMAT_UNSIGNED;
540 image_offset = 0;
541 image_size = buffer_size;
542 }
543 if (image_offset + image_size > buffer_size) {
544 rc = E2BIG;
545 goto fail3;
546 }
547 imagep = (uint8_t *)bufferp + image_offset;
548
549 /* Check unsigned image layout (image header, code, image trailer) */
550 rc = efx_check_unsigned_image(imagep, image_size);
551 if (rc != 0)
552 goto fail4;
553
554 /* Return image details */
555 infop->eii_format = format;
556 infop->eii_imagep = bufferp;
557 infop->eii_image_size = buffer_size;
558 infop->eii_headerp = (efx_image_header_t *)imagep;
559
560 return (0);
561
562fail4:
563 EFSYS_PROBE(fail4);
564fail3:
565 EFSYS_PROBE(fail3);
566fail2:
567 EFSYS_PROBE(fail2);
568 infop->eii_format = EFX_IMAGE_FORMAT_INVALID;
569 infop->eii_imagep = NULL;
570 infop->eii_image_size = 0;
571
572fail1:
573 EFSYS_PROBE1(fail1, efx_rc_t, rc);
574
575 return (rc);
576}
577
578 __checkReturn efx_rc_t
579efx_build_signed_image_write_buffer(
9f95a23c
TL
580 __out_bcount(buffer_size)
581 uint8_t *bufferp,
11fdf7f2
TL
582 __in uint32_t buffer_size,
583 __in efx_image_info_t *infop,
584 __out efx_image_header_t **headerpp)
585{
586 signed_image_chunk_hdr_t chunk_hdr;
587 uint32_t hdr_offset;
588 struct {
589 uint32_t offset;
590 uint32_t size;
591 } cms_header, image_header, code, image_trailer, signature;
592 efx_rc_t rc;
593
594 EFSYS_ASSERT((infop != NULL) && (headerpp != NULL));
595
596 if ((bufferp == NULL) || (buffer_size == 0) ||
597 (infop == NULL) || (headerpp == NULL)) {
598 /* Invalid arguments */
599 rc = EINVAL;
600 goto fail1;
601 }
602 if ((infop->eii_format != EFX_IMAGE_FORMAT_SIGNED) ||
603 (infop->eii_imagep == NULL) ||
604 (infop->eii_headerp == NULL) ||
605 ((uint8_t *)infop->eii_headerp < (uint8_t *)infop->eii_imagep) ||
606 (infop->eii_image_size < EFX_IMAGE_HEADER_SIZE) ||
607 ((size_t)((uint8_t *)infop->eii_headerp - infop->eii_imagep) >
608 (infop->eii_image_size - EFX_IMAGE_HEADER_SIZE))) {
609 /* Invalid image info */
610 rc = EINVAL;
611 goto fail2;
612 }
613
614 /* Locate image chunks in original signed image */
615 cms_header.offset = 0;
616 cms_header.size =
617 (uint32_t)((uint8_t *)infop->eii_headerp - infop->eii_imagep);
618 if ((cms_header.size > buffer_size) ||
619 (cms_header.offset > (buffer_size - cms_header.size))) {
620 rc = EINVAL;
621 goto fail3;
622 }
623
624 image_header.offset = cms_header.offset + cms_header.size;
625 image_header.size = infop->eii_headerp->eih_size;
626 if ((image_header.size > buffer_size) ||
627 (image_header.offset > (buffer_size - image_header.size))) {
628 rc = EINVAL;
629 goto fail4;
630 }
631
632 code.offset = image_header.offset + image_header.size;
633 code.size = infop->eii_headerp->eih_code_size;
634 if ((code.size > buffer_size) ||
635 (code.offset > (buffer_size - code.size))) {
636 rc = EINVAL;
637 goto fail5;
638 }
639
640 image_trailer.offset = code.offset + code.size;
641 image_trailer.size = EFX_IMAGE_TRAILER_SIZE;
642 if ((image_trailer.size > buffer_size) ||
643 (image_trailer.offset > (buffer_size - image_trailer.size))) {
644 rc = EINVAL;
645 goto fail6;
646 }
647
648 signature.offset = image_trailer.offset + image_trailer.size;
649 signature.size = (uint32_t)(infop->eii_image_size - signature.offset);
650 if ((signature.size > buffer_size) ||
651 (signature.offset > (buffer_size - signature.size))) {
652 rc = EINVAL;
653 goto fail7;
654 }
655
656 EFSYS_ASSERT3U(infop->eii_image_size, ==, cms_header.size +
657 image_header.size + code.size + image_trailer.size +
658 signature.size);
659
660 /* BEGIN CSTYLED */
661 /*
662 * Build signed image partition, inserting chunk headers.
663 *
664 * Signed Image: Image in NVRAM partition:
665 *
666 * +-----------------+ +-----------------+
667 * | CMS header | | mcfw.update |<----+
668 * +-----------------+ | | |
669 * | reflash header | +-----------------+ |
670 * +-----------------+ | chunk header: |-->--|-+
671 * | mcfw.update | | REFLASH_TRAILER | | |
672 * | | +-----------------+ | |
673 * +-----------------+ +-->| CMS header | | |
674 * | reflash trailer | | +-----------------+ | |
675 * +-----------------+ | | chunk header: |->-+ | |
676 * | signature | | | REFLASH_HEADER | | | |
677 * +-----------------+ | +-----------------+ | | |
678 * | | reflash header |<--+ | |
679 * | +-----------------+ | |
680 * | | chunk header: |-->--+ |
681 * | | IMAGE | |
682 * | +-----------------+ |
683 * | | reflash trailer |<------+
684 * | +-----------------+
685 * | | chunk header: |
686 * | | SIGNATURE |->-+
687 * | +-----------------+ |
688 * | | signature |<--+
689 * | +-----------------+
690 * | | ...unused... |
691 * | +-----------------+
692 * +-<-| chunk header: |
693 * >-->| CMS_HEADER |
694 * +-----------------+
695 *
696 * Each chunk header gives the partition offset and length of the image
697 * chunk's data. The image chunk data is immediately followed by the
698 * chunk header for the next chunk.
699 *
700 * The data chunk for the firmware code must be at the start of the
701 * partition (needed for the bootloader). The first chunk header in the
702 * chain (for the CMS header) is stored at the end of the partition. The
703 * chain of chunk headers maintains the same logical order of image
704 * chunks as the original signed image file. This set of constraints
705 * results in the layout used for the data chunks and chunk headers.
706 */
707 /* END CSTYLED */
9f95a23c 708 memset(bufferp, 0xFF, buffer_size);
11fdf7f2
TL
709
710 EFX_STATIC_ASSERT(sizeof (chunk_hdr) == SIGNED_IMAGE_CHUNK_HDR_LEN);
711 memset(&chunk_hdr, 0, SIGNED_IMAGE_CHUNK_HDR_LEN);
712
713 /*
714 * CMS header
715 */
716 if (buffer_size < SIGNED_IMAGE_CHUNK_HDR_LEN) {
717 rc = ENOSPC;
718 goto fail8;
719 }
720 hdr_offset = buffer_size - SIGNED_IMAGE_CHUNK_HDR_LEN;
721
722 chunk_hdr.magic = SIGNED_IMAGE_CHUNK_HDR_MAGIC;
723 chunk_hdr.version = SIGNED_IMAGE_CHUNK_HDR_VERSION;
724 chunk_hdr.id = SIGNED_IMAGE_CHUNK_CMS_HEADER;
725 chunk_hdr.offset = code.size + SIGNED_IMAGE_CHUNK_HDR_LEN;
726 chunk_hdr.len = cms_header.size;
727
728 memcpy(bufferp + hdr_offset, &chunk_hdr, sizeof (chunk_hdr));
729
730 if ((chunk_hdr.len > buffer_size) ||
731 (chunk_hdr.offset > (buffer_size - chunk_hdr.len))) {
732 rc = ENOSPC;
733 goto fail9;
734 }
735 memcpy(bufferp + chunk_hdr.offset,
736 infop->eii_imagep + cms_header.offset,
737 cms_header.size);
738
739 /*
740 * Image header
741 */
742 hdr_offset = chunk_hdr.offset + chunk_hdr.len;
743 if (hdr_offset > (buffer_size - SIGNED_IMAGE_CHUNK_HDR_LEN)) {
744 rc = ENOSPC;
745 goto fail10;
746 }
747 chunk_hdr.magic = SIGNED_IMAGE_CHUNK_HDR_MAGIC;
748 chunk_hdr.version = SIGNED_IMAGE_CHUNK_HDR_VERSION;
749 chunk_hdr.id = SIGNED_IMAGE_CHUNK_REFLASH_HEADER;
750 chunk_hdr.offset = hdr_offset + SIGNED_IMAGE_CHUNK_HDR_LEN;
751 chunk_hdr.len = image_header.size;
752
753 memcpy(bufferp + hdr_offset, &chunk_hdr, SIGNED_IMAGE_CHUNK_HDR_LEN);
754
755 if ((chunk_hdr.len > buffer_size) ||
756 (chunk_hdr.offset > (buffer_size - chunk_hdr.len))) {
757 rc = ENOSPC;
758 goto fail11;
759 }
760 memcpy(bufferp + chunk_hdr.offset,
761 infop->eii_imagep + image_header.offset,
762 image_header.size);
763
764 *headerpp = (efx_image_header_t *)(bufferp + chunk_hdr.offset);
765
766 /*
767 * Firmware code
768 */
769 hdr_offset = chunk_hdr.offset + chunk_hdr.len;
770 if (hdr_offset > (buffer_size - SIGNED_IMAGE_CHUNK_HDR_LEN)) {
771 rc = ENOSPC;
772 goto fail12;
773 }
774 chunk_hdr.magic = SIGNED_IMAGE_CHUNK_HDR_MAGIC;
775 chunk_hdr.version = SIGNED_IMAGE_CHUNK_HDR_VERSION;
776 chunk_hdr.id = SIGNED_IMAGE_CHUNK_IMAGE;
777 chunk_hdr.offset = 0;
778 chunk_hdr.len = code.size;
779
780 memcpy(bufferp + hdr_offset, &chunk_hdr, SIGNED_IMAGE_CHUNK_HDR_LEN);
781
782 if ((chunk_hdr.len > buffer_size) ||
783 (chunk_hdr.offset > (buffer_size - chunk_hdr.len))) {
784 rc = ENOSPC;
785 goto fail13;
786 }
787 memcpy(bufferp + chunk_hdr.offset,
788 infop->eii_imagep + code.offset,
789 code.size);
790
791 /*
792 * Image trailer (CRC)
793 */
794 chunk_hdr.magic = SIGNED_IMAGE_CHUNK_HDR_MAGIC;
795 chunk_hdr.version = SIGNED_IMAGE_CHUNK_HDR_VERSION;
796 chunk_hdr.id = SIGNED_IMAGE_CHUNK_REFLASH_TRAILER;
797 chunk_hdr.offset = hdr_offset + SIGNED_IMAGE_CHUNK_HDR_LEN;
798 chunk_hdr.len = image_trailer.size;
799
800 hdr_offset = code.size;
801 if (hdr_offset > (buffer_size - SIGNED_IMAGE_CHUNK_HDR_LEN)) {
802 rc = ENOSPC;
803 goto fail14;
804 }
805
806 memcpy(bufferp + hdr_offset, &chunk_hdr, SIGNED_IMAGE_CHUNK_HDR_LEN);
807
808 if ((chunk_hdr.len > buffer_size) ||
809 (chunk_hdr.offset > (buffer_size - chunk_hdr.len))) {
810 rc = ENOSPC;
811 goto fail15;
812 }
813 memcpy((uint8_t *)bufferp + chunk_hdr.offset,
814 infop->eii_imagep + image_trailer.offset,
815 image_trailer.size);
816
817 /*
818 * Signature
819 */
820 hdr_offset = chunk_hdr.offset + chunk_hdr.len;
821 if (hdr_offset > (buffer_size - SIGNED_IMAGE_CHUNK_HDR_LEN)) {
822 rc = ENOSPC;
823 goto fail16;
824 }
825 chunk_hdr.magic = SIGNED_IMAGE_CHUNK_HDR_MAGIC;
826 chunk_hdr.version = SIGNED_IMAGE_CHUNK_HDR_VERSION;
827 chunk_hdr.id = SIGNED_IMAGE_CHUNK_SIGNATURE;
828 chunk_hdr.offset = chunk_hdr.offset + SIGNED_IMAGE_CHUNK_HDR_LEN;
829 chunk_hdr.len = signature.size;
830
831 memcpy(bufferp + hdr_offset, &chunk_hdr, SIGNED_IMAGE_CHUNK_HDR_LEN);
832
833 if ((chunk_hdr.len > buffer_size) ||
834 (chunk_hdr.offset > (buffer_size - chunk_hdr.len))) {
835 rc = ENOSPC;
836 goto fail17;
837 }
838 memcpy(bufferp + chunk_hdr.offset,
839 infop->eii_imagep + signature.offset,
840 signature.size);
841
842 return (0);
843
844fail17:
845 EFSYS_PROBE(fail17);
846fail16:
847 EFSYS_PROBE(fail16);
848fail15:
849 EFSYS_PROBE(fail15);
850fail14:
851 EFSYS_PROBE(fail14);
852fail13:
853 EFSYS_PROBE(fail13);
854fail12:
855 EFSYS_PROBE(fail12);
856fail11:
857 EFSYS_PROBE(fail11);
858fail10:
859 EFSYS_PROBE(fail10);
860fail9:
861 EFSYS_PROBE(fail9);
862fail8:
863 EFSYS_PROBE(fail8);
864fail7:
865 EFSYS_PROBE(fail7);
866fail6:
867 EFSYS_PROBE(fail6);
868fail5:
869 EFSYS_PROBE(fail5);
870fail4:
871 EFSYS_PROBE(fail4);
872fail3:
873 EFSYS_PROBE(fail3);
874fail2:
875 EFSYS_PROBE(fail2);
876fail1:
877 EFSYS_PROBE1(fail1, efx_rc_t, rc);
878
879 return (rc);
880}
881
882
883
884#endif /* EFSYS_OPT_IMAGE_LAYOUT */
885
886#endif /* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */