1 /*
2  * Copyright 2019-2021, 2023 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 /* Multicore packed image loader implementation */
10 
11 #include <string.h>
12 
13 #include "fsl_common.h"
14 #include "fsl_mpi_loader.h"
15 
16 /*******************************************************************************
17  * Definitions
18  ******************************************************************************/
19 /*****************************************************
20  * TZM preset size definition for different devices. *
21  *****************************************************/
22 #define MPI_TZM_PRESET_SIZE_RT5XX (1140U)
23 #define MPI_TZM_PRESET_SIZE_RT6XX (1052U)
24 
25 #define MPI_ASSERT(x)    \
26     do                   \
27     {                    \
28         if (!(x))        \
29         {                \
30             while (true) \
31             {            \
32             }            \
33         }                \
34     } while (false)
35 
36 #if defined(MIMXRT595S_cm33_SERIES) || defined(MIMXRT555S_SERIES) || defined(MIMXRT533S_SERIES)
37 #define MPI_TZM_PRESET_SIZE MPI_TZM_PRESET_SIZE_RT5XX
38 #define MPI_ADDRESS_MASK    (0xEFFFFFFFU) /* Bit28 is secure address indicator */
39 #define MPI_MEMCPY          (void)memcpy
40 #define MPI_MEMCLR          (void)memset
41 
42 #elif defined(MIMXRT685S_cm33_SERIES) || defined(MIMXRT633S_SERIES)
43 #define MPI_TZM_PRESET_SIZE MPI_TZM_PRESET_SIZE_RT6XX
44 #define MPI_ADDRESS_MASK    (0xEFFFFFFFU) /* Bit28 is secure address indicator */
45 #define MPI_MEMCPY          MPI_WordCopy
46 #define MPI_MEMCLR          MPI_WordSet
47 
48 #else
49 #error "Device not supported by Multicore Packed Image Loader!"
50 #endif
51 
52 /*********************************
53  * Image type fields definition. *
54  *********************************/
55 #define MPI_TYPE_IMAGE_BASE_SHIFT              (0U)
56 #define MPI_TYPE_IMAGE_BASE_MASK               (0xFFU << (MPI_TYPE_IMAGE_BASE_SHIFT))
57 #define MPI_TYPE_IMAGE_BASE_PLAIN_SIGNED       (1U << (MPI_TYPE_IMAGE_BASE_SHIFT))
58 #define MPI_TYPE_IMAGE_BASE_PLAIN_UNSIGNED     (2U << (MPI_TYPE_IMAGE_BASE_SHIFT))
59 #define MPI_TYPE_IMAGE_BASE_ENCRYPTED_SIGNED   (3U << (MPI_TYPE_IMAGE_BASE_SHIFT))
60 #define MPI_TYPE_IMAGE_BASE_XIP_PLAIN_SIGNED   (4U << (MPI_TYPE_IMAGE_BASE_SHIFT))
61 #define MPI_TYPE_IMAGE_BASE_XIP_PLAIN_UNSIGNED (5U << (MPI_TYPE_IMAGE_BASE_SHIFT))
62 
63 #define MPI_TYPE_MULTICORE_PACKED_SHIFT (11U)
64 #define MPI_TYPE_MULTICORE_PACKED_MASK  (1UL << (MPI_TYPE_MULTICORE_PACKED_SHIFT))
65 
66 #define MPI_TYPE_TZM_SHIFT (13U)
67 #define MPI_TYPE_TZM_MASK  (3UL << (MPI_TYPE_TZM_SHIFT))
68 /* Trustzone enabled secure image. */
69 #define MPI_TYPE_TZM_SECURE (0UL << MPI_TYPE_TZM_SHIFT)
70 /* Trustzone enabled secure image with preset values. */
71 #define MPI_TYPE_TZM_SECURE_PRESET (1UL << MPI_TYPE_TZM_SHIFT)
72 /* Trustzone disabled non-secure image entry. */
73 #define MPI_TYPE_TZM_NONSECURE (2UL << MPI_TYPE_TZM_SHIFT)
74 
75 /********************************
76  * Relocation table definition. *
77  ********************************/
78 #define MPI_RELOC_MARKER           (0x4C54424CU)
79 #define MPI_RELOC_FLAG_LTI_LOAD    (1U << 0)
80 #define MPI_RELOC_FLAG_LTI_INIT    (1U << 1)
81 #define MPI_RELOC_FLAG_LTI_OVERLAP (1U << 2)
82 
83 typedef struct
84 {
85     uint32_t srcAddr;
86     uint32_t destAddr;
87     uint32_t segmentSize;
88     uint32_t flags;
89 } mpi_reloc_entry_t;
90 
91 typedef struct
92 {
93     uint32_t marker; /* always set to 0x4C54424C */
94     uint32_t version;
95     uint32_t numberOfEntries;
96     uint32_t entriesOff;
97 } mpi_reloc_table_t;
98 
99 /*******************************************************************************
100  * Prototypes
101  ******************************************************************************/
102 
103 /*******************************************************************************
104  * Variables
105  ******************************************************************************/
106 
107 /*******************************************************************************
108  * Code
109  ******************************************************************************/
110 #if defined(MIMXRT685S_cm33_SERIES) || defined(MIMXRT633S_SERIES)
MPI_WordCopy(void * dest,void * src,uint32_t size)111 static void MPI_WordCopy(void *dest, void *src, uint32_t size)
112 {
113     uint32_t *s, *d;
114 
115     MPI_ASSERT(src != NULL && (((uint32_t)(uint32_t *)src & 3U) == 0U));
116     MPI_ASSERT(dest != NULL && (((uint32_t)(uint32_t *)dest & 3U) == 0U));
117     MPI_ASSERT((size & 3U) == 0U);
118 
119     s = (uint32_t *)src;
120     d = (uint32_t *)dest;
121 
122     while (size > 0U)
123     {
124         *d++ = *s++;
125         size -= 4U;
126     }
127 }
128 
MPI_WordSet(void * ptr,uint32_t value,uint32_t size)129 static void MPI_WordSet(void *ptr, uint32_t value, uint32_t size)
130 {
131     uint32_t *p;
132 
133     MPI_ASSERT(ptr != NULL && (((uint32_t)(uint32_t *)ptr & 3U) == 0U));
134     MPI_ASSERT((size & 3U) == 0U);
135 
136     p = (uint32_t *)ptr;
137 
138     while (size > 0U)
139     {
140         *p++ = value;
141         size -= 4U;
142     }
143 }
144 #endif
145 
MPI_Relocate(uint32_t * vect,mpi_reloc_entry_t * entry)146 static void MPI_Relocate(uint32_t *vect, mpi_reloc_entry_t *entry)
147 {
148     uint32_t srcAddr;
149 
150     MPI_ASSERT(entry != NULL);
151 
152     srcAddr = ((uint32_t)vect) + entry->srcAddr;
153 
154     switch (entry->flags)
155     {
156         case MPI_RELOC_FLAG_LTI_LOAD:
157             if ((srcAddr & MPI_ADDRESS_MASK) != (entry->destAddr & MPI_ADDRESS_MASK))
158             {
159                 MPI_MEMCPY((void *)(uint32_t *)entry->destAddr, (void *)(uint32_t *)srcAddr, entry->segmentSize);
160             }
161             break;
162         case MPI_RELOC_FLAG_LTI_INIT:
163             MPI_MEMCLR((void *)(uint32_t *)entry->destAddr, 0, entry->segmentSize);
164             break;
165         case MPI_RELOC_FLAG_LTI_OVERLAP:
166             /* Do nothing */
167         default:
168             /* Do nothing */
169             break;
170     }
171 }
172 
MPI_HandleRelocTable(uint32_t * vect)173 static void MPI_HandleRelocTable(uint32_t *vect)
174 {
175     uint32_t i;
176     uint32_t imageLen;
177     uint32_t imageType;
178     uint32_t imageBase;
179     uint32_t relocTabEnd;
180     mpi_reloc_table_t *pRelocTab;
181     mpi_reloc_entry_t *pRelocEntry;
182 
183     MPI_ASSERT(vect != NULL);
184 
185     imageLen  = vect[8];
186     imageType = vect[9];
187 
188     if ((imageType & MPI_TYPE_MULTICORE_PACKED_MASK) != 0U)
189     {
190         /* Need to load other images. */
191         imageBase = imageType & MPI_TYPE_IMAGE_BASE_MASK;
192         if (imageBase == MPI_TYPE_IMAGE_BASE_PLAIN_SIGNED || imageBase == MPI_TYPE_IMAGE_BASE_ENCRYPTED_SIGNED ||
193             imageBase == MPI_TYPE_IMAGE_BASE_XIP_PLAIN_SIGNED)
194         {
195             /* Offset 0x28 is certificate header offset. */
196             relocTabEnd = vect[10];
197         }
198         else
199         {
200             /* Offset 0x28 is CRC. */
201             relocTabEnd = imageLen;
202             if ((imageType & MPI_TYPE_TZM_MASK) == MPI_TYPE_TZM_SECURE_PRESET)
203             {
204                 /* Has TZM preset data, need to minus the size for relocation table pointer. */
205                 relocTabEnd -= MPI_TZM_PRESET_SIZE;
206             }
207         }
208         pRelocTab = (mpi_reloc_table_t *)(((uint32_t)vect) + relocTabEnd) - 1;
209         MPI_ASSERT(pRelocTab->marker == MPI_RELOC_MARKER);
210 
211         pRelocEntry = (mpi_reloc_entry_t *)(((uint32_t)vect) + pRelocTab->entriesOff);
212         for (i = 0; i < pRelocTab->numberOfEntries; i++)
213         {
214             MPI_Relocate(vect, pRelocEntry + i);
215         }
216     }
217 }
218 
219 /* Must finish loading before application .data, .bss get initialized. */
MPI_LoadMultiImages(void)220 void MPI_LoadMultiImages(void)
221 {
222     extern uint32_t __VECTOR_TABLE[];
223 
224     MPI_HandleRelocTable(__VECTOR_TABLE);
225 }
226