Commit feb3649257fb84e623d25485c4b9ec64e5d06fc2
Exists in
smarc-8mp-android-11.0.0_2.0.0
and in
1 other branch
Merge remote-tracking branch 'origin/imx_v2020.04' into lf_v2020.04
* origin/imx_v2020.04: MA-18775 system will hang about 3s when boot up kernel MA-18680-2 Support derive rpmb key from BKEK MA-18680-1 Support BKEK generation MLK-25287 imx8mq/mp: Use index parameter of gadget interrupt handler MLK-25271: new qspihdr subsystem for u-boot q(f)spi boot
Showing 24 changed files Side-by-side Diff
- arch/arm/dts/imx8mp-evk.dts
- arch/arm/mach-imx/Kconfig
- arch/arm/mach-imx/Makefile
- arch/arm/mach-imx/cmd_qspihdr.c
- board/freescale/imx8mp_evk/imx8mp_evk.c
- board/freescale/imx8mq_evk/imx8mq_evk.c
- board/freescale/imx8mq_val/imx8mq_val.c
- drivers/crypto/fsl/desc.h
- drivers/crypto/fsl_caam.c
- drivers/fastboot/fb_fsl/fb_fsl_command.c
- include/configs/imx8mm_evk_android.h
- include/configs/imx8mn_evk_android.h
- include/configs/imx8mp_evk_android.h
- include/configs/imx8mq_evk_android.h
- include/fb_fsl.h
- include/fsl_avb.h
- include/fsl_caam.h
- include/interface/storage/storage.h
- include/trusty/rpmb.h
- lib/avb/fsl/fsl_avbkey.c
- lib/avb/fsl/fsl_bootctrl.c
- lib/trusty/ql-tipc/ipc.c
- lib/trusty/ql-tipc/libtipc.c
- lib/trusty/ql-tipc/rpmb_proxy.c
arch/arm/dts/imx8mp-evk.dts
arch/arm/mach-imx/Kconfig
... | ... | @@ -157,6 +157,14 @@ |
157 | 157 | This is similar to kobs-ng, which is used in Linux as separate |
158 | 158 | rootfs package. |
159 | 159 | |
160 | +config CMD_QSPIHDR | |
161 | + bool "Q(F)SPI Boot Config Header command" | |
162 | + depends on DM_SPI_FLASH | |
163 | + default y | |
164 | + help | |
165 | + Boot from Q(F)SPI need a boot config header, this command can | |
166 | + help to check if header already exists or add one if not. | |
167 | + | |
160 | 168 | config FSL_MFGPROT |
161 | 169 | bool "Support the 'mfgprot' command" |
162 | 170 | depends on IMX_HAB || AHAB_BOOT |
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/cmd_qspihdr.c
1 | +// SPDX-License-Identifier: GPL-2.0+ | |
2 | +/* | |
3 | + * Copyright (C) 2021 NXP | |
4 | + */ | |
5 | +#include <common.h> | |
6 | +#include <dm.h> | |
7 | +#include <mapmem.h> | |
8 | +#include <asm/io.h> | |
9 | +#include <spi.h> | |
10 | +#include <spi_flash.h> | |
11 | +#include <dm/device-internal.h> | |
12 | + | |
13 | +static struct spi_flash *flash; | |
14 | + | |
15 | +#define QSPI_HDR_TAG 0xc0ffee01 /* c0ffee01 */ | |
16 | +#define QSPI_HDR_TAG_OFF 0x1fc | |
17 | +#define FSPI_HDR_TAG 0x42464346/* FCFB, bigendian */ | |
18 | +#define FSPI_HDR_TAG_OFF 0x0 | |
19 | + | |
20 | +#define HDR_LEN 0x200 | |
21 | + | |
22 | +#ifdef CONFIG_MX7 | |
23 | +#define QSPI_HDR_OFF 0x0 | |
24 | +#define QSPI_DATA_OFF 0x400 | |
25 | +#else | |
26 | +#define QSPI_HDR_OFF 0x400 | |
27 | +#define QSPI_DATA_OFF 0x1000 | |
28 | +#endif | |
29 | + | |
30 | +#ifdef CONFIG_IMX8MM | |
31 | +#define FSPI_HDR_OFF 0x0 | |
32 | +#define FSPI_DATA_OFF 0x1000 | |
33 | +#else | |
34 | +#define FSPI_HDR_OFF 0x400 | |
35 | +#define FSPI_DATA_OFF 0x1000 | |
36 | +#endif | |
37 | + | |
38 | +#define FLAG_VERBOSE 1 | |
39 | + | |
40 | +struct qspi_config_parameter { | |
41 | + u32 dqs_loopback; /* Sets DQS LoopBack Mode to enable Dummy Pad MCR[24] */ | |
42 | + u32 hold_delay; /* No needed on ULT1 */ | |
43 | + u32 hsphs; /* Half Speed Phase Shift */ | |
44 | + u32 hsdly; /* Half Speed Delay Selection */ | |
45 | + u32 device_quad_mode_en; /* Write Command to Device */ | |
46 | + u32 device_cmd; /* Cmd to xfer to device */ | |
47 | + u32 write_cmd_ipcr; /* IPCR value of Write Cmd */ | |
48 | + u32 write_enable_ipcr; /* IPCR value of Write enable */ | |
49 | + u32 cs_hold_time; /* CS hold time in terms of serial clock.(for example 1 serial clock cyle) */ | |
50 | + u32 cs_setup_time; /* CS setup time in terms of serial clock.(for example 1 serial clock cyle) */ | |
51 | + u32 sflash_A1_size; /* interms of Bytes */ | |
52 | + u32 sflash_A2_size; /* interms of Bytes */ | |
53 | + u32 sflash_B1_size; /* interms of Bytes */ | |
54 | + u32 sflash_B2_size; /* interms of Bytes */ | |
55 | + u32 sclk_freq; /* 0 - 18MHz, 1 - 49MHz, 2 - 55MHz, 3 - 60MHz, 4 - 66Mhz, 5 - 76MHz, 6 - 99MHz (only for SDR Mode) */ | |
56 | + u16 busy_bit_offset; /* Flash device busy bit offset in status register */ | |
57 | + u16 busy_bit_polarity; /* Polarity of busy bit, 0 means the busy bit is 1 while busy and vice versa. */ | |
58 | + u32 sflash_type; /* 1 - Single, 2 - Dual, 4 - Quad */ | |
59 | + u32 sflash_port; /* 0 - Only Port-A, 1 - Both PortA and PortB */ | |
60 | + u32 ddr_mode_enable; /* Enable DDR mode if set to TRUE */ | |
61 | + u32 dqs_enable; /* Enable DQS mode if set to TRUE. Bit 0 represents DQS_EN, bit 1 represents DQS_LAT_EN */ | |
62 | + u32 parallel_mode_enable; /* Enable Individual or parrallel mode. */ | |
63 | + u32 portA_cs1; /* Enable Port A CS1 */ | |
64 | + u32 portB_cs1; /* Enable Port B CS1 */ | |
65 | + u32 fsphs; /* Full Speed Phase Selection */ | |
66 | + u32 fsdly; /* Full Speed Phase Selection */ | |
67 | + u32 ddrsmp; /* Select the sampling point for incoming data when serial flash is in DDR mode. */ | |
68 | + u32 command_seq[64]; /* Set of seq to perform optimum read on SFLASH as as per vendor SFLASH */ | |
69 | + u32 read_status_ipcr; /* IPCR value of Read Status Reg */ | |
70 | + u32 enable_dqs_phase; /* Enable DQS phase */ | |
71 | + u32 config_cmds_en; /* Enable config commands */ | |
72 | + u32 config_cmds[4]; /* config commands, used to configure nor flash */ | |
73 | + u32 config_cmds_args[4]; /* config commands argu */ | |
74 | + u32 dqs_pad_setting_override; /* DQS pin pad setting override */ | |
75 | + u32 sclk_pad_setting_override; /* SCLK pin pad setting override */ | |
76 | + u32 data_pad_setting_override; /* DATA pins pad setting override */ | |
77 | + u32 cs_pad_setting_override; /* CS pins pad setting override */ | |
78 | + u32 dqs_loopback_internal; /* 0: dqs loopback from pad, 1: dqs loopback internally */ | |
79 | + u32 dqs_phase_sel; /* dqs phase sel */ | |
80 | + u32 dqs_fa_delay_chain_sel; /* dqs fa delay chain selection */ | |
81 | + u32 dqs_fb_delay_chain_sel; /* dqs fb delay chain selection */ | |
82 | + u32 sclk_fa_delay_chain_sel; /* sclk fa delay chain selection */ | |
83 | + u32 sclk_fb_delay_chain_sel; /* sclk fb delay chain selection */ | |
84 | + u32 misc_clock_enable; /* Misc clock enable, bit 0 means differential clock enable, bit 1 means CK2 clock enable. */ | |
85 | + u32 reserve[15]; /* Reserved area, the total size of configuration structure should be 512 bytes */ | |
86 | + u32 tag; /* QSPI configuration TAG, should be 0xc0ffee01 */ | |
87 | +}; | |
88 | + | |
89 | +struct fspi_config_parameter { | |
90 | + u32 tag; /* tag, 0x46434642 ascii 'FCFB' */ | |
91 | + u32 version; /* 0x00000156 ascii bugfix | minor | major | 'V' */ | |
92 | + u16 reserved; | |
93 | + u8 reserved0[2]; | |
94 | + u8 readSampleClkSrc; /* 0 - internal loopback, 1 - loopback from DQS pad, 2 - loopback from SCK pad, 3 - Flash provided DQS */ | |
95 | + u8 dataHoldTime; /* CS hold time */ | |
96 | + u8 dataSetupTime; /* CS setup time */ | |
97 | + u8 columnAddressWidth; /* 3 - for HyperFlash, 0 - other devices */ | |
98 | + u8 deviceModeCfgEnable; /* device mode configuration enable feature, 0 - disable, 1- enable */ | |
99 | + u8 reserved1[3]; | |
100 | + u32 deviceModeSeq; /* sequence parameter for device mode configuration */ | |
101 | + u32 deviceModeArg; /* device mode argument, effective only when deviceModeCfgEnable = 1 */ | |
102 | + u8 configCmdEnable; /* config command enable feature, 0 - disable, 1 - enable */ | |
103 | + u8 reserved2[3]; | |
104 | + u32 configCmdSeqs[4]; /* sequences for config command, allow 4 separate configuration command sequences */ | |
105 | + u32 configCmdArgs[4]; /* arguments for each separate configuration command sequence */ | |
106 | + u32 controllerMiscOption; | |
107 | + /* | |
108 | + * | |
109 | + * +--------+----------------------------------------------------------+ | |
110 | + * | offset | description | | |
111 | + * +--------+----------------------------------------------------------+ | |
112 | + * | | differential clock enable | | |
113 | + * | 0 | | | |
114 | + * | | 0 - differential clock is not supported | | |
115 | + * | | 1 - differential clock is supported | | |
116 | + * +--------+----------------------------------------------------------+ | |
117 | + * | | CK2 enable | | |
118 | + * | 1 | | | |
119 | + * | | must set 0 for this silicon | | |
120 | + * | | | | |
121 | + * +--------+----------------------------------------------------------+ | |
122 | + * | | parallel mode enable | | |
123 | + * | 2 | | | |
124 | + * | | must set 0 for this silicon | | |
125 | + * | | | | |
126 | + * +--------+----------------------------------------------------------+ | |
127 | + * | | word addressable enable | | |
128 | + * | 3 | | | |
129 | + * | | 0 - device is not word addressable | | |
130 | + * | | 1 - device is word addressable | | |
131 | + * +--------+----------------------------------------------------------+ | |
132 | + * | | safe configuration frequency enable | | |
133 | + * | 4 | | | |
134 | + * | | 0 - configure external device using specified frequency | | |
135 | + * | | 1 - configure external device using 30MHz | | |
136 | + * +--------+----------------------------------------------------------+ | |
137 | + * | 5 | reserved | | |
138 | + * +--------+----------------------------------------------------------+ | |
139 | + * | | ddr mode enable | | |
140 | + * | 6 | | | |
141 | + * | | 0 - external device works using SDR commands | | |
142 | + * | | 1 - external device works using DDR commands | | |
143 | + * +--------+----------------------------------------------------------+ | |
144 | + */ | |
145 | + u8 deviceType; /* 1 - serial NOR */ | |
146 | + u8 sflashPadType; /* 1 - single pad, 2 - dual pads, 4 - quad pads, 8 - octal pads */ | |
147 | + u8 serialClkFreq; /* 1 - 20MHz, 2 - 50MHz, 3 - 60MHz, 4 - 80MHz, 5 - 100MHz, 6 - 133MHz, 7 - 166MHz, other values - 20MHz*/ | |
148 | + u8 lutCustomSeqEnable; /* 0 - use pre-defined LUT sequence index and number, 1 - use LUT sequence parameters provided in this block */ | |
149 | + u32 reserved3[2]; | |
150 | + u32 sflashA1Size; /* For SPI NOR, need to fill with actual size, in terms of bytes */ | |
151 | + u32 sflashA2Size; /* same as above */ | |
152 | + u32 sflashB1Size; /* same as above */ | |
153 | + u32 sflashB2Size; /* same as above */ | |
154 | + u32 csPadSettingOverride; /* set to 0 if it is not supported */ | |
155 | + u32 sclkPadSettingOverride; /* set to 0 if it is not supported */ | |
156 | + u32 dataPadSettingOverride; /* set to 0 if it is not supported */ | |
157 | + u32 dqsPadSettingOverride; /* set to 0 if it is not supported */ | |
158 | + u32 timeoutInMs; /* maximum wait time during dread busy status, not used in ROM */ | |
159 | + u32 commandInterval; /* interval of CS deselected period, set to 0 */ | |
160 | + u16 dataValidTime[2]; /* time from clock edge to data valid edge */ | |
161 | + /* This field is used when the FlexSPI root clock is less than 100MHz and the read sample */ | |
162 | + /* clock source is device provided DQS signal without CK2 support. */ | |
163 | + /* [31:16] - data valid time for DLLB in terms of 0.1ns */ | |
164 | + /* [15:0] - data valid time for DLLA in terms of 0.1ns */ | |
165 | + u16 busyOffset; /* busy bit offset, valid range: 0 - 31 */ | |
166 | + u16 busyBitPolarity; /* 0 - busy bit is 1 if device is busy, 1 - busy bit is 0 if device is busy */ | |
167 | + u32 lookupTable[64]; /* lookup table */ | |
168 | + u32 lutCustomSeq[12]; /* customized LUT sequence */ | |
169 | + u32 reserved4[4]; | |
170 | + u32 pageSize; /* page size of serial NOR flash, not used in ROM */ | |
171 | + u32 sectorSize; /* sector size of serial NOR flash, not used in ROM */ | |
172 | + u32 reserved5[14]; | |
173 | +}; | |
174 | + | |
175 | +struct header_config { | |
176 | + union { | |
177 | + struct qspi_config_parameter qspi_hdr_config; | |
178 | + struct fspi_config_parameter fspi_hdr_config; | |
179 | + }; | |
180 | +}; | |
181 | + | |
182 | +#if defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_ARCH_MX7ULP) | |
183 | +static struct qspi_config_parameter qspi_safe_config = { | |
184 | + .cs_hold_time = 3, | |
185 | + .cs_setup_time = 3, | |
186 | + .sflash_A1_size = 0x4000000, | |
187 | + .sflash_B1_size = 0x4000000, | |
188 | + .sflash_type = 1, | |
189 | + .command_seq[0] = 0x08180403, | |
190 | + .command_seq[1] = 0x24001c00, | |
191 | + .tag = 0xc0ffee01, | |
192 | +}; | |
193 | + | |
194 | +static struct header_config *safe_config = (struct header_config *)&qspi_safe_config; | |
195 | +#else | |
196 | +static struct fspi_config_parameter fspi_safe_config = { | |
197 | + .tag = 0x42464346, | |
198 | + .version = 0x56010000, | |
199 | + .dataHoldTime = 0x3, | |
200 | + .dataSetupTime = 0x3, | |
201 | + .deviceType = 0x1, | |
202 | + .sflashPadType = 0x1, | |
203 | + .serialClkFreq = 0x2, | |
204 | + .sflashA1Size = 0x10000000, | |
205 | + .lookupTable[0] = 0x0818040b, | |
206 | + .lookupTable[1] = 0x24043008, | |
207 | +}; | |
208 | + | |
209 | +static struct header_config *safe_config = (struct header_config *)&fspi_safe_config; | |
210 | +#endif | |
211 | + | |
212 | +static int qspi_erase_update(struct spi_flash *flash, int off, int len, void *buf) | |
213 | +{ | |
214 | + int size; | |
215 | + int ret; | |
216 | + | |
217 | + size = ROUND(len, flash->sector_size); | |
218 | + ret = spi_flash_erase(flash, off, size); | |
219 | + printf("Erase %#x bytes @ %#x %s\n", | |
220 | + size, off, ret ? "ERROR" : "OK"); | |
221 | + if (ret) | |
222 | + return ret; | |
223 | + | |
224 | + ret = spi_flash_write(flash, off, len, buf); | |
225 | + printf("Write %#x bytes @ %#x %s\n", | |
226 | + len, off, ret ? "ERROR" : "OK"); | |
227 | + | |
228 | + return ret; | |
229 | +} | |
230 | + | |
231 | +static int do_qspihdr_check(int argc, char * const argv[], int flag) | |
232 | +{ | |
233 | + u32 buf; | |
234 | + unsigned long addr; | |
235 | + char *endp; | |
236 | + void *tmp; | |
237 | + | |
238 | +#if defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_ARCH_MX7ULP) | |
239 | + int off = QSPI_HDR_OFF + QSPI_HDR_TAG_OFF; | |
240 | + int tag = QSPI_HDR_TAG; | |
241 | +#else | |
242 | + int off = FSPI_HDR_OFF + FSPI_HDR_TAG_OFF; | |
243 | + int tag = FSPI_HDR_TAG; | |
244 | +#endif | |
245 | + | |
246 | + if (argc == 3) { | |
247 | + /* check data in memory */ | |
248 | + addr = simple_strtoul(argv[2], &endp, 16); | |
249 | + | |
250 | + tmp = map_physmem(addr + off, 4, MAP_WRBACK); | |
251 | + if (!tmp && addr) { | |
252 | + printf("Failed to map physical memory\n"); | |
253 | + return 1; | |
254 | + } | |
255 | + | |
256 | + if (*(u32 *)tmp == tag) { | |
257 | + if (flag & FLAG_VERBOSE) | |
258 | + printf("Found boot config header in memory\n"); | |
259 | + unmap_physmem(tmp, 4); | |
260 | + return 0; | |
261 | + } else { | |
262 | + if (flag & FLAG_VERBOSE) | |
263 | + printf("NO boot config header in memory\n"); | |
264 | + unmap_physmem(tmp, 4); | |
265 | + return 1; | |
266 | + } | |
267 | + } else { | |
268 | + spi_flash_read(flash, off, 4, &buf); | |
269 | + | |
270 | + if (buf == tag) { | |
271 | + if (flag & FLAG_VERBOSE) | |
272 | + printf("Found boot config header in Q(F)SPI\n"); | |
273 | + return 0; | |
274 | + } else { | |
275 | + if (flag & FLAG_VERBOSE) | |
276 | + printf("NO boot config header in Q(F)SPI\n"); | |
277 | + return 1; | |
278 | + } | |
279 | + } | |
280 | +} | |
281 | + | |
282 | +static void hdr_dump(void *data) | |
283 | +{ | |
284 | +#if defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_ARCH_MX7ULP) | |
285 | + struct qspi_config_parameter *hdr = | |
286 | + (struct qspi_config_parameter *)data; | |
287 | +#else | |
288 | + struct fspi_config_parameter *hdr = | |
289 | + (struct fspi_config_parameter *)data; | |
290 | +#endif | |
291 | + int i; | |
292 | + | |
293 | +#define PH(mem, cnt) ( \ | |
294 | +{ \ | |
295 | + if (cnt > 1) { \ | |
296 | + int len = strlen(#mem); \ | |
297 | + char *sub = strchr(#mem, '['); \ | |
298 | + *sub = '\0'; \ | |
299 | + for (i = 0; i < cnt; ++i) \ | |
300 | + printf(" %s[%02d%-*s = %08x\n", \ | |
301 | + #mem, i, 25 - len, "]", \ | |
302 | + (u32)*(&hdr->mem + i)); \ | |
303 | + } else { \ | |
304 | + printf(" %-25s = %0*x\n", \ | |
305 | + #mem, (int)sizeof(hdr->mem), hdr->mem); \ | |
306 | + } \ | |
307 | +} \ | |
308 | +) | |
309 | + | |
310 | +#if defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_ARCH_MX7ULP) | |
311 | + PH(dqs_loopback, 1); | |
312 | + PH(hold_delay, 1); | |
313 | + PH(hsphs, 1); | |
314 | + PH(hsdly, 1); | |
315 | + PH(device_quad_mode_en, 1); | |
316 | + PH(write_cmd_ipcr, 1); | |
317 | + PH(write_enable_ipcr, 1); | |
318 | + PH(cs_hold_time, 1); | |
319 | + PH(cs_setup_time, 1); | |
320 | + PH(sflash_A1_size, 1); | |
321 | + PH(sflash_A2_size, 1); | |
322 | + PH(sflash_B1_size, 1); | |
323 | + PH(sflash_B2_size, 1); | |
324 | + PH(sclk_freq, 1); | |
325 | + PH(busy_bit_offset, 1); | |
326 | + PH(busy_bit_polarity, 1); | |
327 | + PH(sflash_type, 1); | |
328 | + PH(sflash_port, 1); | |
329 | + PH(ddr_mode_enable, 1); | |
330 | + PH(dqs_enable, 1); | |
331 | + PH(parallel_mode_enable, 1); | |
332 | + PH(portA_cs1, 1); | |
333 | + PH(portB_cs1, 1); | |
334 | + PH(fsphs, 1); | |
335 | + PH(fsdly, 1); | |
336 | + PH(ddrsmp, 1); | |
337 | + PH(command_seq[0], 64); | |
338 | + PH(read_status_ipcr, 1); | |
339 | + PH(enable_dqs_phase, 1); | |
340 | + PH(config_cmds_en, 1); | |
341 | + PH(config_cmds[0], 4); | |
342 | + PH(config_cmds_args[0], 4); | |
343 | + PH(dqs_pad_setting_override, 1); | |
344 | + PH(sclk_pad_setting_override, 1); | |
345 | + PH(data_pad_setting_override, 1); | |
346 | + PH(cs_pad_setting_override, 1); | |
347 | + PH(dqs_loopback_internal, 1); | |
348 | + PH(dqs_phase_sel, 1); | |
349 | + PH(dqs_fa_delay_chain_sel, 1); | |
350 | + PH(dqs_fb_delay_chain_sel, 1); | |
351 | + PH(sclk_fa_delay_chain_sel, 1); | |
352 | + PH(sclk_fb_delay_chain_sel, 1); | |
353 | + PH(misc_clock_enable, 1); | |
354 | + PH(tag, 1); | |
355 | +#else | |
356 | + PH(tag, 1); | |
357 | + PH(version, 1); | |
358 | + PH(readSampleClkSrc, 1); | |
359 | + PH(dataHoldTime, 1); | |
360 | + PH(dataSetupTime, 1); | |
361 | + PH(columnAddressWidth, 1); | |
362 | + PH(deviceModeCfgEnable, 1); | |
363 | + PH(deviceModeSeq, 1); | |
364 | + PH(deviceModeArg, 1); | |
365 | + PH(configCmdEnable, 1); | |
366 | + PH(configCmdSeqs[0], 4); | |
367 | + PH(configCmdArgs[0], 4); | |
368 | + PH(controllerMiscOption, 1); | |
369 | + PH(deviceType, 1); | |
370 | + PH(sflashPadType, 1); | |
371 | + PH(serialClkFreq, 1); | |
372 | + PH(lutCustomSeqEnable, 1); | |
373 | + PH(sflashA1Size, 1); | |
374 | + PH(sflashA2Size, 1); | |
375 | + PH(sflashB1Size, 1); | |
376 | + PH(sflashB2Size, 1); | |
377 | + PH(csPadSettingOverride, 1); | |
378 | + PH(sclkPadSettingOverride, 1); | |
379 | + PH(dataPadSettingOverride, 1); | |
380 | + PH(dqsPadSettingOverride, 1); | |
381 | + PH(timeoutInMs, 1); | |
382 | + PH(commandInterval, 1); | |
383 | + PH(dataValidTime[0], 2); | |
384 | + PH(busyOffset, 1); | |
385 | + PH(busyBitPolarity, 1); | |
386 | + PH(lookupTable[0], 64); | |
387 | + PH(lutCustomSeq[0], 12); | |
388 | + PH(pageSize, 1); | |
389 | + PH(sectorSize, 1); | |
390 | +#endif | |
391 | +} | |
392 | + | |
393 | +static int do_qspihdr_dump(int argc, char * const argv[]) | |
394 | +{ | |
395 | + unsigned long addr; | |
396 | + char *endp; | |
397 | + void *tmp; | |
398 | + void *buf; | |
399 | + | |
400 | +#if defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_ARCH_MX7ULP) | |
401 | + int off = QSPI_HDR_OFF; | |
402 | +#else | |
403 | + int off = FSPI_HDR_OFF; | |
404 | +#endif | |
405 | + | |
406 | + if (argc == 3) { | |
407 | + /* check data in memory */ | |
408 | + if (do_qspihdr_check(3, argv, FLAG_VERBOSE)) { | |
409 | + /* return 0 in any cases */ | |
410 | + return 0; | |
411 | + } | |
412 | + | |
413 | + addr = simple_strtoul(argv[2], &endp, 16); | |
414 | + | |
415 | + tmp = map_physmem(addr + off, HDR_LEN, MAP_WRBACK); | |
416 | + if (!tmp && addr) { | |
417 | + printf("Failed to map physical memory\n"); | |
418 | + return 1; | |
419 | + } | |
420 | + | |
421 | + hdr_dump(tmp); | |
422 | + unmap_physmem(tmp, HDR_LEN); | |
423 | + } else { | |
424 | + /* check data in Q(F)SPI */ | |
425 | + buf = malloc(HDR_LEN); | |
426 | + if (!buf) { | |
427 | + printf("Failed to alloc memory\n"); | |
428 | + /* return 0 in any cases */ | |
429 | + return 0; | |
430 | + } | |
431 | + | |
432 | + spi_flash_read(flash, off, HDR_LEN, buf); | |
433 | + | |
434 | + hdr_dump(buf); | |
435 | + free(buf); | |
436 | + } | |
437 | + | |
438 | + return 0; | |
439 | +} | |
440 | + | |
441 | +static int do_qspihdr_init(int argc, char * const argv[]) | |
442 | +{ | |
443 | + unsigned long addr, len; | |
444 | + char *endp; | |
445 | + int total_len; | |
446 | + void *tmp; | |
447 | + void *buf; | |
448 | + bool hdr_flag = false; | |
449 | + int ret; | |
450 | + | |
451 | +#if defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_ARCH_MX7ULP) | |
452 | + int hdr_off = QSPI_HDR_OFF; | |
453 | + int data_off = QSPI_DATA_OFF; | |
454 | +#else | |
455 | + int hdr_off = FSPI_HDR_OFF; | |
456 | + int data_off = FSPI_DATA_OFF; | |
457 | + | |
458 | + safe_config->fspi_hdr_config.pageSize = flash->page_size; | |
459 | + safe_config->fspi_hdr_config.sectorSize = flash->sector_size; | |
460 | +#endif | |
461 | + | |
462 | + addr = simple_strtoul(argv[2], &endp, 16); | |
463 | + len = simple_strtoul(argv[3], &endp, 16); | |
464 | + | |
465 | + total_len = data_off + len; | |
466 | + if (total_len > flash->size) { | |
467 | + printf("Error: length %lx over flash size (%#x)\n", | |
468 | + len, flash->size); | |
469 | + return 1; | |
470 | + } | |
471 | + | |
472 | + /* check if header exists in this memory area*/ | |
473 | + if (do_qspihdr_check(3, argv, 0) == 0) | |
474 | + hdr_flag = true; | |
475 | + | |
476 | + tmp = map_physmem(addr, len, MAP_WRBACK); | |
477 | + if (!tmp && addr) { | |
478 | + printf("Failed to map physical memory\n"); | |
479 | + return 1; | |
480 | + } | |
481 | + | |
482 | + if (hdr_flag) | |
483 | + goto burn_image; | |
484 | + | |
485 | + buf = malloc(total_len); | |
486 | + if (!buf) { | |
487 | + printf("Failed to alloc memory\n"); | |
488 | + unmap_physmem(tmp, total_len); | |
489 | + return 1; | |
490 | + } | |
491 | + | |
492 | + memset(buf, 0xff, total_len); | |
493 | + memcpy(buf + hdr_off, safe_config, HDR_LEN); | |
494 | + memcpy(buf + data_off, tmp, len); | |
495 | + | |
496 | +burn_image: | |
497 | + if (hdr_flag) { | |
498 | + ret = qspi_erase_update(flash, 0, len, tmp); | |
499 | + } else { | |
500 | + ret = qspi_erase_update(flash, 0, total_len, buf); | |
501 | + free(buf); | |
502 | + } | |
503 | + | |
504 | + unmap_physmem(tmp, total_len); | |
505 | + return ret; | |
506 | +} | |
507 | + | |
508 | +static int do_qspihdr_update(int argc, char * const argv[]) | |
509 | +{ | |
510 | + int len; | |
511 | + int size; | |
512 | + void *buf; | |
513 | + int ret; | |
514 | + | |
515 | +#if defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_ARCH_MX7ULP) | |
516 | + int hdr_off = QSPI_HDR_OFF; | |
517 | +#else | |
518 | + int hdr_off = FSPI_HDR_OFF; | |
519 | +#endif | |
520 | + | |
521 | + len = hdr_off + HDR_LEN; | |
522 | + size = ROUND(len, flash->sector_size); | |
523 | + | |
524 | + buf = malloc(size); | |
525 | + if (!buf) { | |
526 | + printf("Failed to alloc memory\n"); | |
527 | + return 1; | |
528 | + } | |
529 | + | |
530 | + spi_flash_read(flash, 0, size, buf); | |
531 | + memcpy(buf + hdr_off, safe_config, HDR_LEN); | |
532 | + | |
533 | + ret = qspi_erase_update(flash, 0, size, buf); | |
534 | + free(buf); | |
535 | + | |
536 | + return ret; | |
537 | +} | |
538 | + | |
539 | +static int do_qspihdr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | |
540 | +{ | |
541 | + char *cmd; | |
542 | + unsigned int bus = CONFIG_SF_DEFAULT_BUS; | |
543 | + unsigned int cs = CONFIG_SF_DEFAULT_CS; | |
544 | + unsigned int speed = CONFIG_SF_DEFAULT_SPEED; | |
545 | + unsigned int mode = CONFIG_SF_DEFAULT_MODE; | |
546 | + int flags = 0; | |
547 | + int ret; | |
548 | + | |
549 | + if (argc < 2) | |
550 | + goto usage; | |
551 | + | |
552 | +#ifdef CONFIG_DM_SPI_FLASH | |
553 | + struct udevice *new, *bus_dev; | |
554 | + | |
555 | + ret = spi_find_bus_and_cs(bus, cs, &bus_dev, &new); | |
556 | + if (!ret) | |
557 | + device_remove(new, DM_REMOVE_NORMAL); | |
558 | + flash = NULL; | |
559 | + ret = spi_flash_probe_bus_cs(bus, cs, speed, mode, &new); | |
560 | + if (ret) { | |
561 | + printf("Failed to initialize SPI flash at %u:%u (error %d)\n", | |
562 | + bus, cs, ret); | |
563 | + return 1; | |
564 | + } | |
565 | + flash = dev_get_uclass_priv(new); | |
566 | +#endif | |
567 | + | |
568 | + cmd = argv[1]; | |
569 | + | |
570 | + if (strcmp(cmd, "check") == 0) | |
571 | + return do_qspihdr_check(argc, argv, flags | FLAG_VERBOSE); | |
572 | + | |
573 | + if (strcmp(cmd, "dump") == 0) | |
574 | + return do_qspihdr_dump(argc, argv); | |
575 | + | |
576 | + if (strcmp(cmd, "init") == 0) { | |
577 | + if (argc < 5) | |
578 | + goto usage; | |
579 | + return do_qspihdr_init(argc, argv); | |
580 | + } | |
581 | + | |
582 | + if (strcmp(cmd, "update") == 0) { | |
583 | + if (argc < 3) | |
584 | + goto usage; | |
585 | + return do_qspihdr_update(argc, argv); | |
586 | + } | |
587 | + | |
588 | + return 0; | |
589 | +usage: | |
590 | + return CMD_RET_USAGE; | |
591 | +} | |
592 | + | |
593 | +static char qspihdr_help_text[] = | |
594 | + "check [addr] - check if boot config already exists, 0-yes, 1-no\n" | |
595 | + " with addr, it will check data in memory of this addr\n" | |
596 | + " without addr, it will check data in Q(F)SPI chip\n" | |
597 | + "qspihdr dump [addr] - dump the header information, if exists\n" | |
598 | + " with addr, it will check data in memory of this addr\n" | |
599 | + " without addr, it will check data in Q(F)SPI chip\n" | |
600 | + "qspihdr init addr len safe - burn data to Q(F)SPI with header\n" | |
601 | + " if data contains header, it will be used, otherwise,\n" | |
602 | + " safe: most common header, single line, sdr, low freq\n" | |
603 | + "qspihdr update safe - only update the header in Q(F)SPI\n"; | |
604 | + | |
605 | +U_BOOT_CMD(qspihdr, 5, 1, do_qspihdr, | |
606 | + "Q(F)SPI Boot Config sub-system", | |
607 | + qspihdr_help_text | |
608 | +); |
board/freescale/imx8mp_evk/imx8mp_evk.c
board/freescale/imx8mq_evk/imx8mq_evk.c
board/freescale/imx8mq_val/imx8mq_val.c
drivers/crypto/fsl/desc.h
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | |
16 | 16 | #define KEY_BLOB_SIZE 32 |
17 | 17 | #define MAC_SIZE 16 |
18 | +#define BKEK_SIZE 32 | |
18 | 19 | |
19 | 20 | /* Max size of any CAAM descriptor in 32-bit words, inclusive of header */ |
20 | 21 | #define MAX_CAAM_DESCSIZE 64 |
... | ... | @@ -462,6 +463,9 @@ |
462 | 463 | #define OP_PROTINFO_HASH_SHA256 0x00000180 |
463 | 464 | #define OP_PROTINFO_HASH_SHA384 0x00000200 |
464 | 465 | #define OP_PROTINFO_HASH_SHA512 0x00000280 |
466 | + | |
467 | +/* PROTINFO fields for Blob Operations */ | |
468 | +#define OP_PROTINFO_MKVB 0x00000002 | |
465 | 469 | |
466 | 470 | /* For non-protocol/alg-only op commands */ |
467 | 471 | #define OP_ALG_TYPE_SHIFT 24 |
drivers/crypto/fsl_caam.c
... | ... | @@ -250,6 +250,42 @@ |
250 | 250 | } |
251 | 251 | |
252 | 252 | /*! |
253 | + * Use CAAM to derive BKEK | |
254 | + * | |
255 | + * @param output_ptr Location address of the output data. | |
256 | + * | |
257 | + * @return SUCCESS or ERROR_XXX | |
258 | + */ | |
259 | +u32 caam_derive_bkek(u8 *output_ptr) | |
260 | +{ | |
261 | + u32 ret = SUCCESS; | |
262 | + u32 key_sz = sizeof(skeymod); | |
263 | + u32 *bkek_desc = g_jrdata.desc; | |
264 | + | |
265 | + /* initialize the output array */ | |
266 | + memset(output_ptr, 0, BKEK_SIZE); | |
267 | + | |
268 | + /* prepare job descriptor */ | |
269 | + init_job_desc(bkek_desc, 0); | |
270 | + append_load(bkek_desc, PTR2CAAMDMA(skeymod), key_sz, | |
271 | + LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY); | |
272 | + append_seq_out_ptr_intlen(bkek_desc, PTR2CAAMDMA(output_ptr), BKEK_SIZE, 0); | |
273 | + append_operation(bkek_desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB | OP_PROTINFO_MKVB); | |
274 | + | |
275 | + flush_dcache_range((uintptr_t)output_ptr & ALIGN_MASK, | |
276 | + ((uintptr_t)output_ptr & ALIGN_MASK) | |
277 | + + ROUND(BKEK_SIZE, ARCH_DMA_MINALIGN)); | |
278 | + | |
279 | + ret = do_job(bkek_desc); | |
280 | + | |
281 | + if (ret != SUCCESS) { | |
282 | + printf("Error: output bkek job failed 0x%x\n", ret); | |
283 | + } | |
284 | + | |
285 | + return ret; | |
286 | +} | |
287 | + | |
288 | +/*! | |
253 | 289 | * Initialize the CAAM. |
254 | 290 | * |
255 | 291 | */ |
drivers/fastboot/fb_fsl/fb_fsl_command.c
... | ... | @@ -45,6 +45,7 @@ |
45 | 45 | |
46 | 46 | #ifdef CONFIG_IMX_TRUSTY_OS |
47 | 47 | #include "u-boot/sha256.h" |
48 | +#include "trusty/rpmb.h" | |
48 | 49 | #include <trusty/libtipc.h> |
49 | 50 | #endif |
50 | 51 | |
51 | 52 | |
52 | 53 | |
... | ... | @@ -696,18 +697,26 @@ |
696 | 697 | } |
697 | 698 | #endif |
698 | 699 | #ifndef CONFIG_AVB_ATX |
699 | - else if (endswith(cmd, FASTBOOT_SET_RPMB_KEY)) { | |
700 | - if (fastboot_set_rpmb_key(fastboot_buf_addr, fastboot_bytes_received)) { | |
701 | - printf("ERROR set rpmb key failed!\n"); | |
702 | - strcpy(response, "FAILset rpmb key failed!"); | |
700 | + else if (endswith(cmd, FASTBOOT_SET_RPMB_STAGED_KEY)) { | |
701 | + if (fastboot_set_rpmb_staged_key(fastboot_buf_addr, fastboot_bytes_received)) { | |
702 | + printf("ERROR set rpmb staged key failed!\n"); | |
703 | + strcpy(response, "FAILset rpmb staged key failed!"); | |
703 | 704 | } else |
704 | 705 | strcpy(response, "OKAY"); |
705 | - } else if (endswith(cmd, FASTBOOT_SET_RPMB_RANDOM_KEY)) { | |
706 | - if (fastboot_set_rpmb_random_key()) { | |
707 | - printf("ERROR set rpmb random key failed!\n"); | |
708 | - strcpy(response, "FAILset rpmb random key failed!"); | |
706 | + } else if (endswith(cmd, FASTBOOT_SET_RPMB_HARDWARE_KEY)) { | |
707 | + if (fastboot_set_rpmb_hardware_key()) { | |
708 | + printf("ERROR set rpmb hardware key failed!\n"); | |
709 | + strcpy(response, "FAILset rpmb hardware key failed!"); | |
709 | 710 | } else |
710 | 711 | strcpy(response, "OKAY"); |
712 | + } else if (endswith(cmd, FASTBOOT_ERASE_RPMB)) { | |
713 | + if (storage_erase_rpmb()) { | |
714 | + printf("ERROR erase rpmb storage failed!\n"); | |
715 | + strcpy(response, "FAILerase rpmb storage failed!"); | |
716 | + } else { | |
717 | + printf("erase rpmb storage succeed!\n"); | |
718 | + strcpy(response, "OKAY"); | |
719 | + } | |
711 | 720 | } else if (endswith(cmd, FASTBOOT_SET_VBMETA_PUBLIC_KEY)) { |
712 | 721 | if (avb_set_public_key(fastboot_buf_addr, |
713 | 722 | fastboot_bytes_received)) |
include/configs/imx8mm_evk_android.h
... | ... | @@ -31,7 +31,8 @@ |
31 | 31 | #define ANDROID_MCU_FIRMWARE_HEADER_STACK 0x20020000 |
32 | 32 | #endif |
33 | 33 | |
34 | -#if !defined(CONFIG_IMX_TRUSTY_OS) || !defined(CONFIG_DUAL_BOOTLOADER) | |
34 | +#if !defined(CONFIG_IMX_TRUSTY_OS) || !defined(CONFIG_DUAL_BOOTLOADER) || \ | |
35 | + !defined(CONFIG_SPL_BUILD) | |
35 | 36 | #undef CONFIG_FSL_CAAM_KB |
36 | 37 | #endif |
37 | 38 |
include/configs/imx8mn_evk_android.h
... | ... | @@ -31,7 +31,8 @@ |
31 | 31 | #define ANDROID_MCU_FIRMWARE_HEADER_STACK 0x20020000 |
32 | 32 | #endif |
33 | 33 | |
34 | -#if !defined(CONFIG_IMX_TRUSTY_OS) || !defined(CONFIG_DUAL_BOOTLOADER) | |
34 | +#if !defined(CONFIG_IMX_TRUSTY_OS) || !defined(CONFIG_DUAL_BOOTLOADER) || \ | |
35 | + !defined(CONFIG_SPL_BUILD) | |
35 | 36 | #undef CONFIG_FSL_CAAM_KB |
36 | 37 | #endif |
37 | 38 |
include/configs/imx8mp_evk_android.h
... | ... | @@ -31,7 +31,8 @@ |
31 | 31 | #define ANDROID_MCU_FIRMWARE_HEADER_STACK 0x20020000 |
32 | 32 | #endif |
33 | 33 | |
34 | -#if !defined(CONFIG_IMX_TRUSTY_OS) || !defined(CONFIG_DUAL_BOOTLOADER) | |
34 | +#if !defined(CONFIG_IMX_TRUSTY_OS) || !defined(CONFIG_DUAL_BOOTLOADER) || \ | |
35 | + !defined(CONFIG_SPL_BUILD) | |
35 | 36 | #undef CONFIG_FSL_CAAM_KB |
36 | 37 | #endif |
37 | 38 |
include/configs/imx8mq_evk_android.h
... | ... | @@ -31,7 +31,8 @@ |
31 | 31 | #define ANDROID_MCU_FIRMWARE_HEADER_STACK 0x20020000 |
32 | 32 | #endif |
33 | 33 | |
34 | -#if !defined(CONFIG_IMX_TRUSTY_OS) || !defined(CONFIG_DUAL_BOOTLOADER) | |
34 | +#if !defined(CONFIG_IMX_TRUSTY_OS) || !defined(CONFIG_DUAL_BOOTLOADER) || \ | |
35 | + !defined(CONFIG_SPL_BUILD) | |
35 | 36 | #undef CONFIG_FSL_CAAM_KB |
36 | 37 | #endif |
37 | 38 |
include/fb_fsl.h
... | ... | @@ -86,9 +86,10 @@ |
86 | 86 | |
87 | 87 | #ifdef CONFIG_IMX_TRUSTY_OS |
88 | 88 | #ifndef CONFIG_AVB_ATX |
89 | -#define FASTBOOT_SET_RPMB_KEY "set-rpmb-key" | |
90 | -#define FASTBOOT_SET_RPMB_RANDOM_KEY "set-rpmb-random-key" | |
89 | +#define FASTBOOT_SET_RPMB_STAGED_KEY "set-rpmb-staged-key" | |
90 | +#define FASTBOOT_SET_RPMB_HARDWARE_KEY "set-rpmb-hardware-key" | |
91 | 91 | #define FASTBOOT_SET_VBMETA_PUBLIC_KEY "set-public-key" |
92 | +#define FASTBOOT_ERASE_RPMB "erase-rpmb" | |
92 | 93 | #endif |
93 | 94 | |
94 | 95 | #define FASTBOOT_SET_CA_RESP "at-set-ca-response" |
include/fsl_avb.h
... | ... | @@ -172,10 +172,10 @@ |
172 | 172 | int avb_atx_fuse_perm_attr(uint8_t *staged_buffer, uint32_t size); |
173 | 173 | |
174 | 174 | /* Initialize rpmb key with the staged key */ |
175 | -int fastboot_set_rpmb_key(uint8_t *staged_buf, uint32_t key_size); | |
175 | +int fastboot_set_rpmb_staged_key(uint8_t *staged_buf, uint32_t key_size); | |
176 | 176 | |
177 | -/* Initialize rpmb key with random key which is generated by caam rng */ | |
178 | -int fastboot_set_rpmb_random_key(void); | |
177 | +/* Initialize rpmb key with hardware key which is derived from BKEK */ | |
178 | +int fastboot_set_rpmb_hardware_key(void); | |
179 | 179 | |
180 | 180 | /* Generate ATX unlock challenge */ |
181 | 181 | int avb_atx_get_unlock_challenge(struct AvbAtxOps* atx_ops, |
include/fsl_caam.h
... | ... | @@ -74,6 +74,7 @@ |
74 | 74 | //////////////////////////////////////////////////////////////////////////////// |
75 | 75 | uint32_t caam_decap_blob(uint32_t plain_text, uint32_t blob_addr, uint32_t size); |
76 | 76 | uint32_t caam_hwrng(uint8_t *output_ptr, uint32_t output_len); |
77 | +uint32_t caam_derive_bkek(u8 *output_ptr); | |
77 | 78 | |
78 | 79 | #endif /* __CAAM_H__ */ |
include/interface/storage/storage.h
include/trusty/rpmb.h
... | ... | @@ -75,5 +75,15 @@ |
75 | 75 | */ |
76 | 76 | void rpmb_storage_put_ctx(void *dev); |
77 | 77 | |
78 | +/* | |
79 | + * Set rpmb key by secure side. | |
80 | + */ | |
81 | +int storage_set_rpmb_key(void); | |
82 | + | |
83 | +/* | |
84 | + * Erase rpmb storage by secure side. | |
85 | + */ | |
86 | +int storage_erase_rpmb(void); | |
87 | + | |
78 | 88 | #endif /* TRUSTY_RPMB_H_ */ |
lib/avb/fsl/fsl_avbkey.c
... | ... | @@ -26,6 +26,7 @@ |
26 | 26 | #include "debug.h" |
27 | 27 | #include <memalign.h> |
28 | 28 | #include "trusty/hwcrypto.h" |
29 | +#include "trusty/rpmb.h" | |
29 | 30 | #include "fsl_atx_attributes.h" |
30 | 31 | #include <asm/mach-imx/hab.h> |
31 | 32 | #include <asm/arch/sys_proto.h> |
32 | 33 | |
... | ... | @@ -301,12 +302,18 @@ |
301 | 302 | ret = -1; |
302 | 303 | goto fail; |
303 | 304 | } |
304 | - /* copy rpmb key to blob */ | |
305 | - memcpy(blob, kp.rpmb_keyblob, RPMBKEY_BLOB_LEN); | |
306 | 305 | caam_open(); |
307 | - if (caam_decap_blob((ulong)extract_key, (ulong)blob, | |
308 | - RPMBKEY_LENGTH)) { | |
309 | - ERR("decap rpmb key error\n"); | |
306 | + if (!strcmp(kp.magic, KEYPACK_MAGIC)) { | |
307 | + /* Use the key from keyslot. */ | |
308 | + memcpy(blob, kp.rpmb_keyblob, RPMBKEY_BLOB_LEN); | |
309 | + if (caam_decap_blob((ulong)extract_key, (ulong)blob, | |
310 | + RPMBKEY_LENGTH)) { | |
311 | + ERR("decap rpmb key error\n"); | |
312 | + ret = -1; | |
313 | + goto fail; | |
314 | + } | |
315 | + } else if (caam_derive_bkek(extract_key)) { | |
316 | + ERR("get rpmb key error\n"); | |
310 | 317 | ret = -1; |
311 | 318 | goto fail; |
312 | 319 | } |
... | ... | @@ -335,6 +342,7 @@ |
335 | 342 | out_buf += cnt; |
336 | 343 | s = 0; |
337 | 344 | } |
345 | + memset(extract_key, 0, RPMBKEY_LENGTH); | |
338 | 346 | ret = 0; |
339 | 347 | |
340 | 348 | fail: |
341 | 349 | |
... | ... | @@ -401,12 +409,18 @@ |
401 | 409 | ret = -1; |
402 | 410 | goto fail; |
403 | 411 | } |
404 | - /* copy rpmb key to blob */ | |
405 | - memcpy(blob, kp.rpmb_keyblob, RPMBKEY_BLOB_LEN); | |
406 | 412 | caam_open(); |
407 | - if (caam_decap_blob((ulong)extract_key, (ulong)blob, | |
408 | - RPMBKEY_LENGTH)) { | |
409 | - ERR("decap rpmb key error\n"); | |
413 | + if (!strcmp(kp.magic, KEYPACK_MAGIC)) { | |
414 | + /* Use the key from keyslot. */ | |
415 | + memcpy(blob, kp.rpmb_keyblob, RPMBKEY_BLOB_LEN); | |
416 | + if (caam_decap_blob((ulong)extract_key, (ulong)blob, | |
417 | + RPMBKEY_LENGTH)) { | |
418 | + ERR("decap rpmb key error\n"); | |
419 | + ret = -1; | |
420 | + goto fail; | |
421 | + } | |
422 | + } else if (caam_derive_bkek(extract_key)) { | |
423 | + ERR("get rpmb key error\n"); | |
410 | 424 | ret = -1; |
411 | 425 | goto fail; |
412 | 426 | } |
... | ... | @@ -440,6 +454,7 @@ |
440 | 454 | if (s != 0) |
441 | 455 | s = 0; |
442 | 456 | } |
457 | + memset(extract_key, 0, RPMBKEY_LENGTH); | |
443 | 458 | ret = 0; |
444 | 459 | |
445 | 460 | fail: |
... | ... | @@ -800,13 +815,8 @@ |
800 | 815 | |
801 | 816 | read_keyslot_package(&kp); |
802 | 817 | if (strcmp(kp.magic, KEYPACK_MAGIC)) { |
803 | - if (rpmbkey_is_set()) { | |
804 | - printf("\nFATAL - RPMB key was destroyed!\n"); | |
805 | - hang(); | |
806 | - } else { | |
807 | - printf("keyslot package magic error, do nothing here!\n"); | |
808 | - return 0; | |
809 | - } | |
818 | + /* Return if the magic doesn't match */ | |
819 | + return 0; | |
810 | 820 | } |
811 | 821 | /* If keyslot package valid, copy it to secure memory */ |
812 | 822 | fill_secure_keyslot_package(&kp); |
... | ... | @@ -1278,7 +1288,7 @@ |
1278 | 1288 | return ret; |
1279 | 1289 | } |
1280 | 1290 | |
1281 | -int fastboot_set_rpmb_key(uint8_t *staged_buf, uint32_t key_size) | |
1291 | +int fastboot_set_rpmb_staged_key(uint8_t *staged_buf, uint32_t key_size) | |
1282 | 1292 | { |
1283 | 1293 | |
1284 | 1294 | if (memcmp(staged_buf, RPMB_KEY_MAGIC, strlen(RPMB_KEY_MAGIC))) { |
1285 | 1295 | |
... | ... | @@ -1290,16 +1300,9 @@ |
1290 | 1300 | RPMBKEY_LENGTH); |
1291 | 1301 | } |
1292 | 1302 | |
1293 | -int fastboot_set_rpmb_random_key(void) | |
1303 | +int fastboot_set_rpmb_hardware_key(void) | |
1294 | 1304 | { |
1295 | - ALLOC_CACHE_ALIGN_BUFFER(uint8_t, rpmb_key, RPMBKEY_LENGTH); | |
1296 | - | |
1297 | - if (hwcrypto_gen_rng((ulong)rpmb_key, RPMBKEY_LENGTH)) { | |
1298 | - printf("error - can't generate random key!\n"); | |
1299 | - return -1; | |
1300 | - } | |
1301 | - | |
1302 | - return do_rpmb_key_set(rpmb_key, RPMBKEY_LENGTH); | |
1305 | + return storage_set_rpmb_key(); | |
1303 | 1306 | } |
1304 | 1307 | |
1305 | 1308 | int avb_set_public_key(uint8_t *staged_buffer, uint32_t size) { |
lib/avb/fsl/fsl_bootctrl.c
... | ... | @@ -643,13 +643,7 @@ |
643 | 643 | |
644 | 644 | #if !defined(CONFIG_XEN) && defined(CONFIG_IMX_TRUSTY_OS) |
645 | 645 | read_keyslot_package(&kp); |
646 | - if (strcmp(kp.magic, KEYPACK_MAGIC)) { | |
647 | - if (rpmbkey_is_set()) { | |
648 | - printf("\nFATAL - RPMB key was destroyed!\n"); | |
649 | - hang(); | |
650 | - } else | |
651 | - printf("keyslot package magic error, do nothing here!\n"); | |
652 | - } else { | |
646 | + if (!strcmp(kp.magic, KEYPACK_MAGIC)) { | |
653 | 647 | /* Set power-on write protection to boot1 partition. */ |
654 | 648 | if (mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, BOOT1_PWR_WP)) { |
655 | 649 | printf("Unable to set power-on write protection to boot1!\n"); |
lib/trusty/ql-tipc/ipc.c
... | ... | @@ -177,6 +177,8 @@ |
177 | 177 | return rc; |
178 | 178 | } |
179 | 179 | |
180 | +extern bool proxy_resp_flag; | |
181 | + | |
180 | 182 | int trusty_ipc_recv(struct trusty_ipc_chan *chan, |
181 | 183 | const struct trusty_ipc_iovec *iovs, size_t iovs_cnt, |
182 | 184 | bool wait) |
... | ... | @@ -194,9 +196,13 @@ |
194 | 196 | } |
195 | 197 | } |
196 | 198 | |
197 | - rc = trusty_ipc_dev_recv(chan->dev, chan->handle, iovs, iovs_cnt); | |
198 | - if (rc < 0) | |
199 | - trusty_error("%s: ipc recv failed (%d)\n", __func__, rc); | |
199 | + /* Return directly if the iovs have been received. */ | |
200 | + if (!proxy_resp_flag) { | |
201 | + rc = trusty_ipc_dev_recv(chan->dev, chan->handle, iovs, iovs_cnt); | |
202 | + if (rc < 0) | |
203 | + trusty_error("%s: ipc recv failed (%d)\n", __func__, rc); | |
204 | + } else | |
205 | + rc = 0; | |
200 | 206 | |
201 | 207 | return rc; |
202 | 208 | } |
lib/trusty/ql-tipc/libtipc.c
... | ... | @@ -47,6 +47,14 @@ |
47 | 47 | void rpmb_storage_put_ctx(void *dev); |
48 | 48 | void trusty_ipc_shutdown(void) |
49 | 49 | { |
50 | + /** | |
51 | + * Trusty OS is not well initialized when the rpmb | |
52 | + * key is not set, skip ipc shut down to avoid panic. | |
53 | + */ | |
54 | + if (!rpmbkey_is_set()) { | |
55 | + return; | |
56 | + } | |
57 | + | |
50 | 58 | (void)rpmb_storage_proxy_shutdown(_ipc_dev); |
51 | 59 | (void)rpmb_storage_put_ctx(rpmb_ctx); |
52 | 60 | |
... | ... | @@ -67,6 +75,7 @@ |
67 | 75 | int trusty_ipc_init(void) |
68 | 76 | { |
69 | 77 | int rc; |
78 | + bool use_keystore = true; | |
70 | 79 | /* init Trusty device */ |
71 | 80 | trusty_info("Initializing Trusty device\n"); |
72 | 81 | rc = trusty_dev_init(&_tdev, NULL); |
... | ... | @@ -88,8 +97,7 @@ |
88 | 97 | /* start secure storage proxy service */ |
89 | 98 | rc = rpmb_storage_proxy_init(_ipc_dev, rpmb_ctx); |
90 | 99 | if (rc != 0) { |
91 | - trusty_error("Initlializing RPMB storage proxy service failed (%d)\n", | |
92 | - rc); | |
100 | + trusty_error("Initlializing RPMB storage proxy service failed (%d)\n", rc); | |
93 | 101 | #ifndef CONFIG_AVB_ATX |
94 | 102 | /* check if rpmb key has been fused. */ |
95 | 103 | if(rpmbkey_is_set()) { |
96 | 104 | |
97 | 105 | |
... | ... | @@ -98,12 +106,16 @@ |
98 | 106 | hang(); |
99 | 107 | } |
100 | 108 | #else |
101 | - return rc; | |
109 | + return rc; | |
102 | 110 | #endif |
103 | - } else { | |
104 | - /* secure storage service init ok, use trusty backed keystore */ | |
105 | - env_set("keystore", "trusty"); | |
111 | + } | |
106 | 112 | |
113 | + /** | |
114 | + * The proxy service can return success even the storage initialization | |
115 | + * failed (when the rpmb key not set). Init the avb and keymaster service | |
116 | + * only when the rpmb key has been set. | |
117 | + */ | |
118 | + if (rpmbkey_is_set()) { | |
107 | 119 | rc = avb_tipc_init(_ipc_dev); |
108 | 120 | if (rc != 0) { |
109 | 121 | trusty_error("Initlializing Trusty AVB client failed (%d)\n", rc); |
... | ... | @@ -115,7 +127,8 @@ |
115 | 127 | trusty_error("Initlializing Trusty Keymaster client failed (%d)\n", rc); |
116 | 128 | return rc; |
117 | 129 | } |
118 | - } | |
130 | + } else | |
131 | + use_keystore = false; | |
119 | 132 | |
120 | 133 | #ifndef CONFIG_AVB_ATX |
121 | 134 | rc = hwcrypto_tipc_init(_ipc_dev); |
... | ... | @@ -124,6 +137,10 @@ |
124 | 137 | return rc; |
125 | 138 | } |
126 | 139 | #endif |
140 | + | |
141 | + /* secure storage service init ok, use trusty backed keystore */ | |
142 | + if (use_keystore) | |
143 | + env_set("keystore", "trusty"); | |
127 | 144 | |
128 | 145 | return TRUSTY_ERR_NONE; |
129 | 146 | } |
lib/trusty/ql-tipc/rpmb_proxy.c
... | ... | @@ -37,6 +37,8 @@ |
37 | 37 | struct storage_msg req_msg; |
38 | 38 | static uint8_t req_buf[4096]; |
39 | 39 | static uint8_t read_buf[4096]; |
40 | +bool proxy_resp_flag = false; | |
41 | +static int req_len = 0; | |
40 | 42 | |
41 | 43 | /* |
42 | 44 | * Read RPMB request from storage service. Writes message to @msg |
... | ... | @@ -74,6 +76,53 @@ |
74 | 76 | } |
75 | 77 | |
76 | 78 | /* |
79 | + * Read RPMB response from storage service. Writes message to @msg | |
80 | + * and @req. | |
81 | + * | |
82 | + * @chan: proxy ipc channel | |
83 | + * @msg: address of storage message header | |
84 | + * @cmd: cmd corresponding to the request | |
85 | + * @resp: address of storage message response | |
86 | + * @resp_len: length of resp in bytes | |
87 | + */ | |
88 | +static int proxy_read_response(struct trusty_ipc_chan *chan, struct storage_msg *msg, | |
89 | + uint32_t cmd, void *resp, size_t resp_len) | |
90 | +{ | |
91 | + int rc; | |
92 | + | |
93 | + struct trusty_ipc_iovec resp_iovs[2] = { | |
94 | + { .base = msg, .len = sizeof(*msg) }, | |
95 | + { .base = resp, .len = resp_len }, | |
96 | + }; | |
97 | + rc = trusty_ipc_recv(chan, resp_iovs, resp ? 2 : 1, true); | |
98 | + if (rc < 0) { | |
99 | + /* recv message failed */ | |
100 | + trusty_error("%s: failed (%d) to recv response\n", __func__, rc); | |
101 | + return rc; | |
102 | + } | |
103 | + if (proxy_resp_flag) { | |
104 | + memcpy(msg, &req_msg, sizeof(struct storage_msg)); | |
105 | + if (resp) | |
106 | + memcpy(resp, req_buf, req_len); | |
107 | + rc = req_len + sizeof(struct storage_msg); | |
108 | + proxy_resp_flag = false; | |
109 | + } | |
110 | + | |
111 | + if ((size_t)rc < sizeof(*msg)) { | |
112 | + /* malformed message */ | |
113 | + trusty_error("%s: malformed request (%zu)\n", __func__, (size_t)rc); | |
114 | + return TRUSTY_ERR_GENERIC; | |
115 | + } | |
116 | + | |
117 | + if (msg->cmd != (cmd | STORAGE_RESP_BIT)) { | |
118 | + trusty_error("malformed response, cmd: 0x%x\n", msg->cmd); | |
119 | + return TRUSTY_ERR_GENERIC; | |
120 | + } | |
121 | + | |
122 | + return rc - sizeof(*msg); /* return payload size */ | |
123 | +} | |
124 | + | |
125 | +/* | |
77 | 126 | * Send RPMB response to storage service |
78 | 127 | * |
79 | 128 | * @chan: proxy ipc channel |
... | ... | @@ -95,6 +144,71 @@ |
95 | 144 | } |
96 | 145 | |
97 | 146 | /* |
147 | + * Send RPMB request to storage service | |
148 | + * | |
149 | + * @chan: proxy ipc channel | |
150 | + * @msg: address of storage message header | |
151 | + * @req: address of storage message request | |
152 | + * @req_len: length of request in bytes | |
153 | + */ | |
154 | +static int proxy_send_request(struct trusty_ipc_chan *chan, | |
155 | + struct storage_msg *msg, void *req, | |
156 | + size_t req_len) | |
157 | +{ | |
158 | + struct trusty_ipc_iovec req_iovs[2] = { | |
159 | + { .base = msg, .len = sizeof(*msg) }, | |
160 | + { .base = req, .len = req_len } | |
161 | + }; | |
162 | + | |
163 | + return trusty_ipc_send(chan, req_iovs, req ? 2 : 1, false); | |
164 | +} | |
165 | + | |
166 | +/* | |
167 | + * Convenience function to send a request to the storage service and read the | |
168 | + * response. | |
169 | + * | |
170 | + * @cmd: the command | |
171 | + * @req: the request buffer | |
172 | + * @req_size: size of the request buffer | |
173 | + * @resp: the response buffer | |
174 | + * @resp_size_p: pointer to the size of the response buffer. changed to the | |
175 | + actual size of the response read from the secure side | |
176 | + */ | |
177 | +static int storage_do_tipc(uint32_t cmd, void *req, uint32_t req_size, void *resp, | |
178 | + uint32_t *resp_size_p) | |
179 | +{ | |
180 | + int rc; | |
181 | + struct storage_msg msg = { .cmd = cmd }; | |
182 | + | |
183 | + if (!initialized) { | |
184 | + trusty_error("%s: Secure storage TIPC client not initialized\n", __func__); | |
185 | + return TRUSTY_ERR_GENERIC; | |
186 | + } | |
187 | + rc = proxy_send_request(&proxy_chan, &msg, req, req_size); | |
188 | + if (rc < 0) { | |
189 | + trusty_error("%s: failed (%d) to send storage request\n", __func__, rc); | |
190 | + return rc; | |
191 | + } | |
192 | + | |
193 | + uint32_t resp_size = resp_size_p ? *resp_size_p : 0; | |
194 | + rc = proxy_read_response(&proxy_chan, &msg, cmd, resp, resp_size); | |
195 | + if (rc < 0) { | |
196 | + trusty_error("%s: failed (%d) to read secure storage response\n", __func__, rc); | |
197 | + return rc; | |
198 | + } | |
199 | + /* change response size to actual response size */ | |
200 | + if (resp_size_p && rc != *resp_size_p) { | |
201 | + *resp_size_p = rc; | |
202 | + } | |
203 | + if (msg.result != STORAGE_NO_ERROR) { | |
204 | + trusty_error("%s: secure storage service returned error (%d)\n", __func__, | |
205 | + msg.result); | |
206 | + return TRUSTY_ERR_GENERIC; | |
207 | + } | |
208 | + return TRUSTY_ERR_NONE; | |
209 | +} | |
210 | + | |
211 | +/* | |
98 | 212 | * Executes the RPMB request at @r, sends response to storage service. |
99 | 213 | * |
100 | 214 | * @chan: proxy ipc channel |
... | ... | @@ -257,6 +371,18 @@ |
257 | 371 | return rc; |
258 | 372 | } |
259 | 373 | |
374 | + /** | |
375 | + * The response of proxy will also be routed to here but we should | |
376 | + * not handle them, just return and set "proxy_resp_flag" to indicate | |
377 | + * func trusty_ipc_dev_recv() not try to receive the msg again. | |
378 | + */ | |
379 | + if (req_msg.cmd & STORAGE_RESP_BIT) { | |
380 | + chan->complete = 1; | |
381 | + proxy_resp_flag = 1; | |
382 | + req_len = rc; | |
383 | + return TRUSTY_EVENT_HANDLED; | |
384 | + } | |
385 | + | |
260 | 386 | /* handle it and send reply */ |
261 | 387 | rc = proxy_handle_req(chan, &req_msg, req_buf, rc); |
262 | 388 | if (rc < 0) { |
... | ... | @@ -329,5 +455,17 @@ |
329 | 455 | trusty_ipc_close(&proxy_chan); |
330 | 456 | |
331 | 457 | initialized = false; |
458 | +} | |
459 | + | |
460 | +int storage_set_rpmb_key(void) | |
461 | +{ | |
462 | + uint32_t size = 0; | |
463 | + return storage_do_tipc(STORAGE_RPMB_KEY_SET, NULL, 0, NULL, &size); | |
464 | +} | |
465 | + | |
466 | +int storage_erase_rpmb(void) | |
467 | +{ | |
468 | + uint32_t size = 0; | |
469 | + return storage_do_tipc(STORAGE_RPMB_ERASE_ALL, NULL, 0, NULL, &size); | |
332 | 470 | } |