Commit dd058bca4a30fff27bcd643575b2935c706d021b
Committed by
Ye Li
1 parent
5cc3fbe211
Exists in
smarc_8mm-imx_v2018.03_4.14.98_2.0.0_ga
and in
4 other branches
MLK-21174 mx7ulp: hab: Add hab_status command for HABv4 M4 boot
When booting in low power or dual boot modes the M4 binary is authenticated by the M4 ROM code. Add an option in hab_status command so users can retrieve M4 HAB failure and warning events. => hab_status m4 Secure boot disabled HAB Configuration: 0xf0, HAB State: 0x66 No HAB Events Found! Add command documentation in mx6_mx7_secure_boot.txt guide. As HAB M4 API cannot be called from A7 core the code is parsing the M4 HAB persistent memory region. The HAB persistent memory stores HAB events, public keys and others HAB related information. The HAB persistent memory region addresses and sizes can be found in AN12263 "HABv4 RVT Guidelines and Recommendations". Reviewed-by: Utkarsh Gupta <utkarsh.gupta@nxp.com> Reviewed-by: Ye Li <ye.li@nxp.com> Signed-off-by: Breno Lima <breno.lima@nxp.com> (cherry picked from commit 0efff16579fabcf57acb9c8857afac8fb58de355)
Showing 3 changed files with 139 additions and 0 deletions Inline Diff
arch/arm/include/asm/mach-imx/hab.h
1 | /* | 1 | /* |
2 | * Copyright (C) 2012-2015 Freescale Semiconductor, Inc. All Rights Reserved. | 2 | * Copyright (C) 2012-2015 Freescale Semiconductor, Inc. All Rights Reserved. |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: GPL-2.0+ | 4 | * SPDX-License-Identifier: GPL-2.0+ |
5 | * | 5 | * |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #ifndef __SECURE_MX6Q_H__ | 8 | #ifndef __SECURE_MX6Q_H__ |
9 | #define __SECURE_MX6Q_H__ | 9 | #define __SECURE_MX6Q_H__ |
10 | 10 | ||
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <linux/compiler.h> | 12 | #include <linux/compiler.h> |
13 | 13 | ||
14 | /* | 14 | /* |
15 | * IVT header definitions | 15 | * IVT header definitions |
16 | * Security Reference Manual for i.MX 7Dual and 7Solo Applications Processors, | 16 | * Security Reference Manual for i.MX 7Dual and 7Solo Applications Processors, |
17 | * Rev. 0, 03/2017 | 17 | * Rev. 0, 03/2017 |
18 | * Section : 6.7.1.1 | 18 | * Section : 6.7.1.1 |
19 | */ | 19 | */ |
20 | #define IVT_HEADER_MAGIC 0xD1 | 20 | #define IVT_HEADER_MAGIC 0xD1 |
21 | #define IVT_TOTAL_LENGTH 0x20 | 21 | #define IVT_TOTAL_LENGTH 0x20 |
22 | #define IVT_HEADER_V1 0x40 | 22 | #define IVT_HEADER_V1 0x40 |
23 | #define IVT_HEADER_V2 0x41 | 23 | #define IVT_HEADER_V2 0x41 |
24 | 24 | ||
25 | struct __packed ivt_header { | 25 | struct __packed ivt_header { |
26 | uint8_t magic; | 26 | uint8_t magic; |
27 | uint16_t length; | 27 | uint16_t length; |
28 | uint8_t version; | 28 | uint8_t version; |
29 | }; | 29 | }; |
30 | 30 | ||
31 | struct ivt { | 31 | struct ivt { |
32 | struct ivt_header hdr; /* IVT header above */ | 32 | struct ivt_header hdr; /* IVT header above */ |
33 | uint32_t entry; /* Absolute address of first instruction */ | 33 | uint32_t entry; /* Absolute address of first instruction */ |
34 | uint32_t reserved1; /* Reserved should be zero */ | 34 | uint32_t reserved1; /* Reserved should be zero */ |
35 | uint32_t dcd; /* Absolute address of the image DCD */ | 35 | uint32_t dcd; /* Absolute address of the image DCD */ |
36 | uint32_t boot; /* Absolute address of the boot data */ | 36 | uint32_t boot; /* Absolute address of the boot data */ |
37 | uint32_t self; /* Absolute address of the IVT */ | 37 | uint32_t self; /* Absolute address of the IVT */ |
38 | uint32_t csf; /* Absolute address of the CSF */ | 38 | uint32_t csf; /* Absolute address of the CSF */ |
39 | uint32_t reserved2; /* Reserved should be zero */ | 39 | uint32_t reserved2; /* Reserved should be zero */ |
40 | }; | 40 | }; |
41 | 41 | ||
42 | struct __packed hab_hdr { | 42 | struct __packed hab_hdr { |
43 | u8 tag; /* Tag field */ | 43 | u8 tag; /* Tag field */ |
44 | u8 len[2]; /* Length field in bytes (big-endian) */ | 44 | u8 len[2]; /* Length field in bytes (big-endian) */ |
45 | u8 par; /* Parameters field */ | 45 | u8 par; /* Parameters field */ |
46 | }; | 46 | }; |
47 | 47 | ||
48 | /* Default event structure */ | ||
49 | struct __packed evt_def { | ||
50 | struct hab_hdr hdr; /* Header */ | ||
51 | uint32_t sts; /* Status */ | ||
52 | uint32_t ctx; /* Default context */ | ||
53 | uint8_t *data; /* Default data location */ | ||
54 | size_t bytes; /* Size of default data */ | ||
55 | }; | ||
56 | |||
48 | /* -------- start of HAB API updates ------------*/ | 57 | /* -------- start of HAB API updates ------------*/ |
49 | /* The following are taken from HAB4 SIS */ | 58 | /* The following are taken from HAB4 SIS */ |
50 | 59 | ||
51 | /* Status definitions */ | 60 | /* Status definitions */ |
52 | enum hab_status { | 61 | enum hab_status { |
53 | HAB_STS_ANY = 0x00, | 62 | HAB_STS_ANY = 0x00, |
54 | HAB_FAILURE = 0x33, | 63 | HAB_FAILURE = 0x33, |
55 | HAB_WARNING = 0x69, | 64 | HAB_WARNING = 0x69, |
56 | HAB_SUCCESS = 0xf0 | 65 | HAB_SUCCESS = 0xf0 |
57 | }; | 66 | }; |
58 | 67 | ||
59 | /* Security Configuration definitions */ | 68 | /* Security Configuration definitions */ |
60 | enum hab_config { | 69 | enum hab_config { |
61 | HAB_CFG_RETURN = 0x33, /* < Field Return IC */ | 70 | HAB_CFG_RETURN = 0x33, /* < Field Return IC */ |
62 | HAB_CFG_OPEN = 0xf0, /* < Non-secure IC */ | 71 | HAB_CFG_OPEN = 0xf0, /* < Non-secure IC */ |
63 | HAB_CFG_CLOSED = 0xcc /* < Secure IC */ | 72 | HAB_CFG_CLOSED = 0xcc /* < Secure IC */ |
64 | }; | 73 | }; |
65 | 74 | ||
66 | /* State definitions */ | 75 | /* State definitions */ |
67 | enum hab_state { | 76 | enum hab_state { |
68 | HAB_STATE_INITIAL = 0x33, /* Initialising state (transitory) */ | 77 | HAB_STATE_INITIAL = 0x33, /* Initialising state (transitory) */ |
69 | HAB_STATE_CHECK = 0x55, /* Check state (non-secure) */ | 78 | HAB_STATE_CHECK = 0x55, /* Check state (non-secure) */ |
70 | HAB_STATE_NONSECURE = 0x66, /* Non-secure state */ | 79 | HAB_STATE_NONSECURE = 0x66, /* Non-secure state */ |
71 | HAB_STATE_TRUSTED = 0x99, /* Trusted state */ | 80 | HAB_STATE_TRUSTED = 0x99, /* Trusted state */ |
72 | HAB_STATE_SECURE = 0xaa, /* Secure state */ | 81 | HAB_STATE_SECURE = 0xaa, /* Secure state */ |
73 | HAB_STATE_FAIL_SOFT = 0xcc, /* Soft fail state */ | 82 | HAB_STATE_FAIL_SOFT = 0xcc, /* Soft fail state */ |
74 | HAB_STATE_FAIL_HARD = 0xff, /* Hard fail state (terminal) */ | 83 | HAB_STATE_FAIL_HARD = 0xff, /* Hard fail state (terminal) */ |
75 | HAB_STATE_NONE = 0xf0, /* No security state machine */ | 84 | HAB_STATE_NONE = 0xf0, /* No security state machine */ |
76 | HAB_STATE_MAX | 85 | HAB_STATE_MAX |
77 | }; | 86 | }; |
78 | 87 | ||
79 | enum hab_reason { | 88 | enum hab_reason { |
80 | HAB_RSN_ANY = 0x00, /* Match any reason */ | 89 | HAB_RSN_ANY = 0x00, /* Match any reason */ |
81 | HAB_ENG_FAIL = 0x30, /* Engine failure */ | 90 | HAB_ENG_FAIL = 0x30, /* Engine failure */ |
82 | HAB_INV_ADDRESS = 0x22, /* Invalid address: access denied */ | 91 | HAB_INV_ADDRESS = 0x22, /* Invalid address: access denied */ |
83 | HAB_INV_ASSERTION = 0x0c, /* Invalid assertion */ | 92 | HAB_INV_ASSERTION = 0x0c, /* Invalid assertion */ |
84 | HAB_INV_CALL = 0x28, /* Function called out of sequence */ | 93 | HAB_INV_CALL = 0x28, /* Function called out of sequence */ |
85 | HAB_INV_CERTIFICATE = 0x21, /* Invalid certificate */ | 94 | HAB_INV_CERTIFICATE = 0x21, /* Invalid certificate */ |
86 | HAB_INV_COMMAND = 0x06, /* Invalid command: command malformed */ | 95 | HAB_INV_COMMAND = 0x06, /* Invalid command: command malformed */ |
87 | HAB_INV_CSF = 0x11, /* Invalid csf */ | 96 | HAB_INV_CSF = 0x11, /* Invalid csf */ |
88 | HAB_INV_DCD = 0x27, /* Invalid dcd */ | 97 | HAB_INV_DCD = 0x27, /* Invalid dcd */ |
89 | HAB_INV_INDEX = 0x0f, /* Invalid index: access denied */ | 98 | HAB_INV_INDEX = 0x0f, /* Invalid index: access denied */ |
90 | HAB_INV_IVT = 0x05, /* Invalid ivt */ | 99 | HAB_INV_IVT = 0x05, /* Invalid ivt */ |
91 | HAB_INV_KEY = 0x1d, /* Invalid key */ | 100 | HAB_INV_KEY = 0x1d, /* Invalid key */ |
92 | HAB_INV_RETURN = 0x1e, /* Failed callback function */ | 101 | HAB_INV_RETURN = 0x1e, /* Failed callback function */ |
93 | HAB_INV_SIGNATURE = 0x18, /* Invalid signature */ | 102 | HAB_INV_SIGNATURE = 0x18, /* Invalid signature */ |
94 | HAB_INV_SIZE = 0x17, /* Invalid data size */ | 103 | HAB_INV_SIZE = 0x17, /* Invalid data size */ |
95 | HAB_MEM_FAIL = 0x2e, /* Memory failure */ | 104 | HAB_MEM_FAIL = 0x2e, /* Memory failure */ |
96 | HAB_OVR_COUNT = 0x2b, /* Expired poll count */ | 105 | HAB_OVR_COUNT = 0x2b, /* Expired poll count */ |
97 | HAB_OVR_STORAGE = 0x2d, /* Exhausted storage region */ | 106 | HAB_OVR_STORAGE = 0x2d, /* Exhausted storage region */ |
98 | HAB_UNS_ALGORITHM = 0x12, /* Unsupported algorithm */ | 107 | HAB_UNS_ALGORITHM = 0x12, /* Unsupported algorithm */ |
99 | HAB_UNS_COMMAND = 0x03, /* Unsupported command */ | 108 | HAB_UNS_COMMAND = 0x03, /* Unsupported command */ |
100 | HAB_UNS_ENGINE = 0x0a, /* Unsupported engine */ | 109 | HAB_UNS_ENGINE = 0x0a, /* Unsupported engine */ |
101 | HAB_UNS_ITEM = 0x24, /* Unsupported configuration item */ | 110 | HAB_UNS_ITEM = 0x24, /* Unsupported configuration item */ |
102 | HAB_UNS_KEY = 0x1b, /* Unsupported key type/parameters */ | 111 | HAB_UNS_KEY = 0x1b, /* Unsupported key type/parameters */ |
103 | HAB_UNS_PROTOCOL = 0x14, /* Unsupported protocol */ | 112 | HAB_UNS_PROTOCOL = 0x14, /* Unsupported protocol */ |
104 | HAB_UNS_STATE = 0x09, /* Unsuitable state */ | 113 | HAB_UNS_STATE = 0x09, /* Unsuitable state */ |
105 | HAB_RSN_MAX | 114 | HAB_RSN_MAX |
106 | }; | 115 | }; |
107 | 116 | ||
108 | enum hab_context { | 117 | enum hab_context { |
109 | HAB_CTX_ANY = 0x00, /* Match any context */ | 118 | HAB_CTX_ANY = 0x00, /* Match any context */ |
110 | HAB_CTX_FAB = 0xff, /* Event logged in hab_fab_test() */ | 119 | HAB_CTX_FAB = 0xff, /* Event logged in hab_fab_test() */ |
111 | HAB_CTX_ENTRY = 0xe1, /* Event logged in hab_rvt.entry() */ | 120 | HAB_CTX_ENTRY = 0xe1, /* Event logged in hab_rvt.entry() */ |
112 | HAB_CTX_TARGET = 0x33, /* Event logged in hab_rvt.check_target() */ | 121 | HAB_CTX_TARGET = 0x33, /* Event logged in hab_rvt.check_target() */ |
113 | HAB_CTX_AUTHENTICATE = 0x0a,/* Logged in hab_rvt.authenticate_image() */ | 122 | HAB_CTX_AUTHENTICATE = 0x0a,/* Logged in hab_rvt.authenticate_image() */ |
114 | HAB_CTX_DCD = 0xdd, /* Event logged in hab_rvt.run_dcd() */ | 123 | HAB_CTX_DCD = 0xdd, /* Event logged in hab_rvt.run_dcd() */ |
115 | HAB_CTX_CSF = 0xcf, /* Event logged in hab_rvt.run_csf() */ | 124 | HAB_CTX_CSF = 0xcf, /* Event logged in hab_rvt.run_csf() */ |
116 | HAB_CTX_COMMAND = 0xc0, /* Event logged executing csf/dcd command */ | 125 | HAB_CTX_COMMAND = 0xc0, /* Event logged executing csf/dcd command */ |
117 | HAB_CTX_AUT_DAT = 0xdb, /* Authenticated data block */ | 126 | HAB_CTX_AUT_DAT = 0xdb, /* Authenticated data block */ |
118 | HAB_CTX_ASSERT = 0xa0, /* Event logged in hab_rvt.assert() */ | 127 | HAB_CTX_ASSERT = 0xa0, /* Event logged in hab_rvt.assert() */ |
119 | HAB_CTX_EXIT = 0xee, /* Event logged in hab_rvt.exit() */ | 128 | HAB_CTX_EXIT = 0xee, /* Event logged in hab_rvt.exit() */ |
120 | HAB_CTX_MAX | 129 | HAB_CTX_MAX |
121 | }; | 130 | }; |
122 | 131 | ||
123 | enum hab_target { | 132 | enum hab_target { |
124 | HAB_TGT_MEMORY = 0x0f, | 133 | HAB_TGT_MEMORY = 0x0f, |
125 | HAB_TGT_PERIPHERAL = 0xf0, | 134 | HAB_TGT_PERIPHERAL = 0xf0, |
126 | HAB_TGT_ANY = 0x55, | 135 | HAB_TGT_ANY = 0x55, |
127 | }; | 136 | }; |
128 | 137 | ||
129 | struct imx_sec_config_fuse_t { | 138 | struct imx_sec_config_fuse_t { |
130 | int bank; | 139 | int bank; |
131 | int word; | 140 | int word; |
132 | }; | 141 | }; |
133 | 142 | ||
134 | #if defined(CONFIG_SECURE_BOOT) | 143 | #if defined(CONFIG_SECURE_BOOT) |
135 | extern struct imx_sec_config_fuse_t const imx_sec_config_fuse; | 144 | extern struct imx_sec_config_fuse_t const imx_sec_config_fuse; |
136 | #endif | 145 | #endif |
137 | 146 | ||
138 | /*Function prototype description*/ | 147 | /*Function prototype description*/ |
139 | typedef enum hab_status hab_rvt_report_event_t(enum hab_status, uint32_t, | 148 | typedef enum hab_status hab_rvt_report_event_t(enum hab_status, uint32_t, |
140 | uint8_t* , size_t*); | 149 | uint8_t* , size_t*); |
141 | typedef enum hab_status hab_rvt_report_status_t(enum hab_config *, | 150 | typedef enum hab_status hab_rvt_report_status_t(enum hab_config *, |
142 | enum hab_state *); | 151 | enum hab_state *); |
143 | typedef enum hab_status hab_loader_callback_f_t(void**, size_t*, const void*); | 152 | typedef enum hab_status hab_loader_callback_f_t(void**, size_t*, const void*); |
144 | typedef enum hab_status hab_rvt_entry_t(void); | 153 | typedef enum hab_status hab_rvt_entry_t(void); |
145 | typedef enum hab_status hab_rvt_exit_t(void); | 154 | typedef enum hab_status hab_rvt_exit_t(void); |
146 | typedef void *hab_rvt_authenticate_image_t(uint8_t, ptrdiff_t, | 155 | typedef void *hab_rvt_authenticate_image_t(uint8_t, ptrdiff_t, |
147 | void **, size_t *, hab_loader_callback_f_t); | 156 | void **, size_t *, hab_loader_callback_f_t); |
148 | typedef enum hab_status hab_rvt_check_target_t(enum hab_target, const void *, | 157 | typedef enum hab_status hab_rvt_check_target_t(enum hab_target, const void *, |
149 | size_t); | 158 | size_t); |
150 | typedef void hab_rvt_failsafe_t(void); | 159 | typedef void hab_rvt_failsafe_t(void); |
151 | typedef void hapi_clock_init_t(void); | 160 | typedef void hapi_clock_init_t(void); |
152 | 161 | ||
153 | #define HAB_ENG_ANY 0x00 /* Select first compatible engine */ | 162 | #define HAB_ENG_ANY 0x00 /* Select first compatible engine */ |
154 | #define HAB_ENG_SCC 0x03 /* Security controller */ | 163 | #define HAB_ENG_SCC 0x03 /* Security controller */ |
155 | #define HAB_ENG_RTIC 0x05 /* Run-time integrity checker */ | 164 | #define HAB_ENG_RTIC 0x05 /* Run-time integrity checker */ |
156 | #define HAB_ENG_SAHARA 0x06 /* Crypto accelerator */ | 165 | #define HAB_ENG_SAHARA 0x06 /* Crypto accelerator */ |
157 | #define HAB_ENG_CSU 0x0a /* Central Security Unit */ | 166 | #define HAB_ENG_CSU 0x0a /* Central Security Unit */ |
158 | #define HAB_ENG_SRTC 0x0c /* Secure clock */ | 167 | #define HAB_ENG_SRTC 0x0c /* Secure clock */ |
159 | #define HAB_ENG_DCP 0x1b /* Data Co-Processor */ | 168 | #define HAB_ENG_DCP 0x1b /* Data Co-Processor */ |
160 | #define HAB_ENG_CAAM 0x1d /* CAAM */ | 169 | #define HAB_ENG_CAAM 0x1d /* CAAM */ |
161 | #define HAB_ENG_SNVS 0x1e /* Secure Non-Volatile Storage */ | 170 | #define HAB_ENG_SNVS 0x1e /* Secure Non-Volatile Storage */ |
162 | #define HAB_ENG_OCOTP 0x21 /* Fuse controller */ | 171 | #define HAB_ENG_OCOTP 0x21 /* Fuse controller */ |
163 | #define HAB_ENG_DTCP 0x22 /* DTCP co-processor */ | 172 | #define HAB_ENG_DTCP 0x22 /* DTCP co-processor */ |
164 | #define HAB_ENG_ROM 0x36 /* Protected ROM area */ | 173 | #define HAB_ENG_ROM 0x36 /* Protected ROM area */ |
165 | #define HAB_ENG_HDCP 0x24 /* HDCP co-processor */ | 174 | #define HAB_ENG_HDCP 0x24 /* HDCP co-processor */ |
166 | #define HAB_ENG_RTL 0x77 /* RTL simulation engine */ | 175 | #define HAB_ENG_RTL 0x77 /* RTL simulation engine */ |
167 | #define HAB_ENG_SW 0xff /* Software engine */ | 176 | #define HAB_ENG_SW 0xff /* Software engine */ |
168 | 177 | ||
169 | #ifdef CONFIG_ARM64 | 178 | #ifdef CONFIG_ARM64 |
170 | #ifdef CONFIG_IMX8MQ | 179 | #ifdef CONFIG_IMX8MQ |
171 | #define HAB_RVT_BASE 0x00000880 | 180 | #define HAB_RVT_BASE 0x00000880 |
172 | #else | 181 | #else |
173 | #define HAB_RVT_BASE 0x00000900 | 182 | #define HAB_RVT_BASE 0x00000900 |
174 | #endif | 183 | #endif |
175 | 184 | ||
176 | #define HAB_RVT_ENTRY (*(ulong *)(HAB_RVT_BASE + 0x08)) | 185 | #define HAB_RVT_ENTRY (*(ulong *)(HAB_RVT_BASE + 0x08)) |
177 | #define HAB_RVT_EXIT (*(ulong *)(HAB_RVT_BASE + 0x10)) | 186 | #define HAB_RVT_EXIT (*(ulong *)(HAB_RVT_BASE + 0x10)) |
178 | #define HAB_RVT_CHECK_TARGET (*(ulong *)(HAB_RVT_BASE + 0x18)) | 187 | #define HAB_RVT_CHECK_TARGET (*(ulong *)(HAB_RVT_BASE + 0x18)) |
179 | #define HAB_RVT_AUTHENTICATE_IMAGE (*(ulong *)(HAB_RVT_BASE + 0x20)) | 188 | #define HAB_RVT_AUTHENTICATE_IMAGE (*(ulong *)(HAB_RVT_BASE + 0x20)) |
180 | #define HAB_RVT_REPORT_EVENT (*(ulong *)(HAB_RVT_BASE + 0x40)) | 189 | #define HAB_RVT_REPORT_EVENT (*(ulong *)(HAB_RVT_BASE + 0x40)) |
181 | #define HAB_RVT_REPORT_STATUS (*(ulong *)(HAB_RVT_BASE + 0x48)) | 190 | #define HAB_RVT_REPORT_STATUS (*(ulong *)(HAB_RVT_BASE + 0x48)) |
182 | #define HAB_RVT_FAILSAFE (*(ulong *)(HAB_RVT_BASE + 0x50)) | 191 | #define HAB_RVT_FAILSAFE (*(ulong *)(HAB_RVT_BASE + 0x50)) |
183 | #else | 192 | #else |
184 | 193 | ||
185 | #ifdef CONFIG_ROM_UNIFIED_SECTIONS | 194 | #ifdef CONFIG_ROM_UNIFIED_SECTIONS |
186 | #define HAB_RVT_BASE 0x00000100 | 195 | #define HAB_RVT_BASE 0x00000100 |
187 | #else | 196 | #else |
188 | #define HAB_RVT_BASE_NEW 0x00000098 | 197 | #define HAB_RVT_BASE_NEW 0x00000098 |
189 | #define HAB_RVT_BASE_OLD 0x00000094 | 198 | #define HAB_RVT_BASE_OLD 0x00000094 |
190 | #define HAB_RVT_BASE ((is_mx6dqp()) ? \ | 199 | #define HAB_RVT_BASE ((is_mx6dqp()) ? \ |
191 | HAB_RVT_BASE_NEW : \ | 200 | HAB_RVT_BASE_NEW : \ |
192 | (is_mx6dq() && (soc_rev() >= CHIP_REV_1_3)) ? \ | 201 | (is_mx6dq() && (soc_rev() >= CHIP_REV_1_3)) ? \ |
193 | HAB_RVT_BASE_NEW : \ | 202 | HAB_RVT_BASE_NEW : \ |
194 | (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \ | 203 | (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \ |
195 | HAB_RVT_BASE_NEW : HAB_RVT_BASE_OLD) | 204 | HAB_RVT_BASE_NEW : HAB_RVT_BASE_OLD) |
196 | #endif | 205 | #endif |
197 | 206 | ||
198 | #define HAB_RVT_ENTRY (*(uint32_t *)(HAB_RVT_BASE + 0x04)) | 207 | #define HAB_RVT_ENTRY (*(uint32_t *)(HAB_RVT_BASE + 0x04)) |
199 | #define HAB_RVT_EXIT (*(uint32_t *)(HAB_RVT_BASE + 0x08)) | 208 | #define HAB_RVT_EXIT (*(uint32_t *)(HAB_RVT_BASE + 0x08)) |
200 | #define HAB_RVT_CHECK_TARGET (*(uint32_t *)(HAB_RVT_BASE + 0x0C)) | 209 | #define HAB_RVT_CHECK_TARGET (*(uint32_t *)(HAB_RVT_BASE + 0x0C)) |
201 | #define HAB_RVT_AUTHENTICATE_IMAGE (*(uint32_t *)(HAB_RVT_BASE + 0x10)) | 210 | #define HAB_RVT_AUTHENTICATE_IMAGE (*(uint32_t *)(HAB_RVT_BASE + 0x10)) |
202 | #define HAB_RVT_REPORT_EVENT (*(uint32_t *)(HAB_RVT_BASE + 0x20)) | 211 | #define HAB_RVT_REPORT_EVENT (*(uint32_t *)(HAB_RVT_BASE + 0x20)) |
203 | #define HAB_RVT_REPORT_STATUS (*(uint32_t *)(HAB_RVT_BASE + 0x24)) | 212 | #define HAB_RVT_REPORT_STATUS (*(uint32_t *)(HAB_RVT_BASE + 0x24)) |
204 | #define HAB_RVT_FAILSAFE (*(uint32_t *)(HAB_RVT_BASE + 0x28)) | 213 | #define HAB_RVT_FAILSAFE (*(uint32_t *)(HAB_RVT_BASE + 0x28)) |
205 | 214 | ||
206 | #endif /*CONFIG_ARM64*/ | 215 | #endif /*CONFIG_ARM64*/ |
207 | 216 | ||
208 | #define HAB_CID_ROM 0 /**< ROM Caller ID */ | 217 | #define HAB_CID_ROM 0 /**< ROM Caller ID */ |
209 | #define HAB_CID_UBOOT 1 /**< UBOOT Caller ID*/ | 218 | #define HAB_CID_UBOOT 1 /**< UBOOT Caller ID*/ |
210 | 219 | ||
211 | #define HAB_CMD_HDR 0xD4 /* CSF Header */ | 220 | #define HAB_CMD_HDR 0xD4 /* CSF Header */ |
212 | #define HAB_CMD_WRT_DAT 0xCC /* Write Data command tag */ | 221 | #define HAB_CMD_WRT_DAT 0xCC /* Write Data command tag */ |
213 | #define HAB_CMD_CHK_DAT 0xCF /* Check Data command tag */ | 222 | #define HAB_CMD_CHK_DAT 0xCF /* Check Data command tag */ |
214 | #define HAB_CMD_SET 0xB1 /* Set command tag */ | 223 | #define HAB_CMD_SET 0xB1 /* Set command tag */ |
215 | #define HAB_PAR_MID 0x01 /* MID parameter value */ | 224 | #define HAB_PAR_MID 0x01 /* MID parameter value */ |
216 | 225 | ||
217 | #define IVT_SIZE 0x20 | 226 | #define IVT_SIZE 0x20 |
218 | #define CSF_PAD_SIZE 0x2000 | 227 | #define CSF_PAD_SIZE 0x2000 |
228 | |||
229 | #define HAB_TAG_EVT 0xDB | ||
230 | #define HAB_TAG_EVT_DEF 0x0C | ||
231 | |||
232 | #define HAB_MAJ_VER 0x40 | ||
233 | #define HAB_MAJ_MASK 0xF0 | ||
219 | 234 | ||
220 | /* ----------- end of HAB API updates ------------*/ | 235 | /* ----------- end of HAB API updates ------------*/ |
221 | 236 | ||
222 | int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size, | 237 | int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size, |
223 | uint32_t ivt_offset); | 238 | uint32_t ivt_offset); |
224 | bool imx_hab_is_enabled(void); | 239 | bool imx_hab_is_enabled(void); |
225 | 240 | ||
226 | #endif | 241 | #endif |
227 | 242 |
arch/arm/mach-imx/hab.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2010-2015 Freescale Semiconductor, Inc. | 2 | * Copyright (C) 2010-2015 Freescale Semiconductor, Inc. |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: GPL-2.0+ | 4 | * SPDX-License-Identifier: GPL-2.0+ |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <common.h> | 7 | #include <common.h> |
8 | #include <config.h> | 8 | #include <config.h> |
9 | #include <fuse.h> | 9 | #include <fuse.h> |
10 | #include <asm/io.h> | 10 | #include <asm/io.h> |
11 | #include <asm/system.h> | 11 | #include <asm/system.h> |
12 | #include <asm/arch/clock.h> | 12 | #include <asm/arch/clock.h> |
13 | #include <asm/arch/sys_proto.h> | 13 | #include <asm/arch/sys_proto.h> |
14 | #include <asm/mach-imx/hab.h> | 14 | #include <asm/mach-imx/hab.h> |
15 | 15 | ||
16 | DECLARE_GLOBAL_DATA_PTR; | 16 | DECLARE_GLOBAL_DATA_PTR; |
17 | 17 | ||
18 | #define ALIGN_SIZE 0x1000 | 18 | #define ALIGN_SIZE 0x1000 |
19 | #define MX6DQ_PU_IROM_MMU_EN_VAR 0x009024a8 | 19 | #define MX6DQ_PU_IROM_MMU_EN_VAR 0x009024a8 |
20 | #define MX6DLS_PU_IROM_MMU_EN_VAR 0x00901dd0 | 20 | #define MX6DLS_PU_IROM_MMU_EN_VAR 0x00901dd0 |
21 | #define MX6SL_PU_IROM_MMU_EN_VAR 0x00900a18 | 21 | #define MX6SL_PU_IROM_MMU_EN_VAR 0x00900a18 |
22 | #define IS_HAB_ENABLED_BIT \ | 22 | #define IS_HAB_ENABLED_BIT \ |
23 | (is_soc_type(MXC_SOC_MX7ULP) ? 0x80000000 : \ | 23 | (is_soc_type(MXC_SOC_MX7ULP) ? 0x80000000 : \ |
24 | ((is_soc_type(MXC_SOC_MX7) || is_soc_type(MXC_SOC_IMX8M))? 0x2000000 : 0x2)) | 24 | ((is_soc_type(MXC_SOC_MX7) || is_soc_type(MXC_SOC_IMX8M))? 0x2000000 : 0x2)) |
25 | 25 | ||
26 | #ifdef CONFIG_MX7ULP | ||
27 | #define HAB_M4_PERSISTENT_START ((soc_rev() >= CHIP_REV_2_0) ? 0x20008040 : \ | ||
28 | 0x20008180) | ||
29 | #define HAB_M4_PERSISTENT_BYTES 0xB80 | ||
30 | #endif | ||
31 | |||
26 | static int ivt_header_error(const char *err_str, struct ivt_header *ivt_hdr) | 32 | static int ivt_header_error(const char *err_str, struct ivt_header *ivt_hdr) |
27 | { | 33 | { |
28 | printf("%s magic=0x%x length=0x%02x version=0x%x\n", err_str, | 34 | printf("%s magic=0x%x length=0x%02x version=0x%x\n", err_str, |
29 | ivt_hdr->magic, ivt_hdr->length, ivt_hdr->version); | 35 | ivt_hdr->magic, ivt_hdr->length, ivt_hdr->version); |
30 | 36 | ||
31 | return 1; | 37 | return 1; |
32 | } | 38 | } |
33 | 39 | ||
34 | static int verify_ivt_header(struct ivt_header *ivt_hdr) | 40 | static int verify_ivt_header(struct ivt_header *ivt_hdr) |
35 | { | 41 | { |
36 | int result = 0; | 42 | int result = 0; |
37 | 43 | ||
38 | if (ivt_hdr->magic != IVT_HEADER_MAGIC) | 44 | if (ivt_hdr->magic != IVT_HEADER_MAGIC) |
39 | result = ivt_header_error("bad magic", ivt_hdr); | 45 | result = ivt_header_error("bad magic", ivt_hdr); |
40 | 46 | ||
41 | if (be16_to_cpu(ivt_hdr->length) != IVT_TOTAL_LENGTH) | 47 | if (be16_to_cpu(ivt_hdr->length) != IVT_TOTAL_LENGTH) |
42 | result = ivt_header_error("bad length", ivt_hdr); | 48 | result = ivt_header_error("bad length", ivt_hdr); |
43 | 49 | ||
44 | if (ivt_hdr->version != IVT_HEADER_V1 && | 50 | if (ivt_hdr->version != IVT_HEADER_V1 && |
45 | ivt_hdr->version != IVT_HEADER_V2) | 51 | ivt_hdr->version != IVT_HEADER_V2) |
46 | result = ivt_header_error("bad version", ivt_hdr); | 52 | result = ivt_header_error("bad version", ivt_hdr); |
47 | 53 | ||
48 | return result; | 54 | return result; |
49 | } | 55 | } |
50 | 56 | ||
51 | #ifdef CONFIG_ARM64 | 57 | #ifdef CONFIG_ARM64 |
52 | #define FSL_SIP_HAB 0xC2000007 | 58 | #define FSL_SIP_HAB 0xC2000007 |
53 | #define FSL_SIP_HAB_AUTHENTICATE 0x00 | 59 | #define FSL_SIP_HAB_AUTHENTICATE 0x00 |
54 | #define FSL_SIP_HAB_ENTRY 0x01 | 60 | #define FSL_SIP_HAB_ENTRY 0x01 |
55 | #define FSL_SIP_HAB_EXIT 0x02 | 61 | #define FSL_SIP_HAB_EXIT 0x02 |
56 | #define FSL_SIP_HAB_REPORT_EVENT 0x03 | 62 | #define FSL_SIP_HAB_REPORT_EVENT 0x03 |
57 | #define FSL_SIP_HAB_REPORT_STATUS 0x04 | 63 | #define FSL_SIP_HAB_REPORT_STATUS 0x04 |
58 | #define FSL_SIP_HAB_FAILSAFE 0x05 | 64 | #define FSL_SIP_HAB_FAILSAFE 0x05 |
59 | #define FSL_SIP_HAB_CHECK_TARGET 0x06 | 65 | #define FSL_SIP_HAB_CHECK_TARGET 0x06 |
60 | static volatile gd_t *gd_save; | 66 | static volatile gd_t *gd_save; |
61 | #endif | 67 | #endif |
62 | 68 | ||
63 | static inline void save_gd(void) | 69 | static inline void save_gd(void) |
64 | { | 70 | { |
65 | #ifdef CONFIG_ARM64 | 71 | #ifdef CONFIG_ARM64 |
66 | gd_save = gd; | 72 | gd_save = gd; |
67 | #endif | 73 | #endif |
68 | } | 74 | } |
69 | 75 | ||
70 | static inline void restore_gd(void) | 76 | static inline void restore_gd(void) |
71 | { | 77 | { |
72 | #ifdef CONFIG_ARM64 | 78 | #ifdef CONFIG_ARM64 |
73 | /* | 79 | /* |
74 | * Make will already error that reserving x18 is not supported at the | 80 | * Make will already error that reserving x18 is not supported at the |
75 | * time of writing, clang: error: unknown argument: '-ffixed-x18' | 81 | * time of writing, clang: error: unknown argument: '-ffixed-x18' |
76 | */ | 82 | */ |
77 | __asm__ volatile("mov x18, %0\n" : : "r" (gd_save)); | 83 | __asm__ volatile("mov x18, %0\n" : : "r" (gd_save)); |
78 | #endif | 84 | #endif |
79 | } | 85 | } |
80 | 86 | ||
81 | enum hab_status hab_rvt_report_event(enum hab_status status, uint32_t index, | 87 | enum hab_status hab_rvt_report_event(enum hab_status status, uint32_t index, |
82 | uint8_t *event, size_t *bytes) | 88 | uint8_t *event, size_t *bytes) |
83 | { | 89 | { |
84 | enum hab_status ret; | 90 | enum hab_status ret; |
85 | hab_rvt_report_event_t *hab_rvt_report_event_func; | 91 | hab_rvt_report_event_t *hab_rvt_report_event_func; |
86 | hab_rvt_report_event_func = (hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT; | 92 | hab_rvt_report_event_func = (hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT; |
87 | 93 | ||
88 | #if defined(CONFIG_ARM64) | 94 | #if defined(CONFIG_ARM64) |
89 | if (current_el() != 3) { | 95 | if (current_el() != 3) { |
90 | /* call sip */ | 96 | /* call sip */ |
91 | ret = (enum hab_status)call_imx_sip(FSL_SIP_HAB, FSL_SIP_HAB_REPORT_EVENT, (unsigned long)index, | 97 | ret = (enum hab_status)call_imx_sip(FSL_SIP_HAB, FSL_SIP_HAB_REPORT_EVENT, (unsigned long)index, |
92 | (unsigned long)event, (unsigned long)bytes); | 98 | (unsigned long)event, (unsigned long)bytes); |
93 | return ret; | 99 | return ret; |
94 | } | 100 | } |
95 | #endif | 101 | #endif |
96 | 102 | ||
97 | save_gd(); | 103 | save_gd(); |
98 | ret = hab_rvt_report_event_func(status, index, event, bytes); | 104 | ret = hab_rvt_report_event_func(status, index, event, bytes); |
99 | restore_gd(); | 105 | restore_gd(); |
100 | 106 | ||
101 | return ret; | 107 | return ret; |
102 | 108 | ||
103 | } | 109 | } |
104 | 110 | ||
105 | enum hab_status hab_rvt_report_status(enum hab_config *config, | 111 | enum hab_status hab_rvt_report_status(enum hab_config *config, |
106 | enum hab_state *state) | 112 | enum hab_state *state) |
107 | { | 113 | { |
108 | enum hab_status ret; | 114 | enum hab_status ret; |
109 | hab_rvt_report_status_t *hab_rvt_report_status_func; | 115 | hab_rvt_report_status_t *hab_rvt_report_status_func; |
110 | hab_rvt_report_status_func = (hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS; | 116 | hab_rvt_report_status_func = (hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS; |
111 | 117 | ||
112 | #if defined(CONFIG_ARM64) | 118 | #if defined(CONFIG_ARM64) |
113 | if (current_el() != 3) { | 119 | if (current_el() != 3) { |
114 | /* call sip */ | 120 | /* call sip */ |
115 | ret = (enum hab_status)call_imx_sip(FSL_SIP_HAB, FSL_SIP_HAB_REPORT_STATUS, | 121 | ret = (enum hab_status)call_imx_sip(FSL_SIP_HAB, FSL_SIP_HAB_REPORT_STATUS, |
116 | (unsigned long)config, (unsigned long)state, 0); | 122 | (unsigned long)config, (unsigned long)state, 0); |
117 | return ret; | 123 | return ret; |
118 | } | 124 | } |
119 | #endif | 125 | #endif |
120 | 126 | ||
121 | save_gd(); | 127 | save_gd(); |
122 | ret = hab_rvt_report_status_func(config, state); | 128 | ret = hab_rvt_report_status_func(config, state); |
123 | restore_gd(); | 129 | restore_gd(); |
124 | 130 | ||
125 | return ret; | 131 | return ret; |
126 | } | 132 | } |
127 | 133 | ||
128 | enum hab_status hab_rvt_entry(void) | 134 | enum hab_status hab_rvt_entry(void) |
129 | { | 135 | { |
130 | enum hab_status ret; | 136 | enum hab_status ret; |
131 | hab_rvt_entry_t *hab_rvt_entry_func; | 137 | hab_rvt_entry_t *hab_rvt_entry_func; |
132 | hab_rvt_entry_func = (hab_rvt_entry_t *)HAB_RVT_ENTRY; | 138 | hab_rvt_entry_func = (hab_rvt_entry_t *)HAB_RVT_ENTRY; |
133 | 139 | ||
134 | #if defined(CONFIG_ARM64) | 140 | #if defined(CONFIG_ARM64) |
135 | if (current_el() != 3) { | 141 | if (current_el() != 3) { |
136 | /* call sip */ | 142 | /* call sip */ |
137 | ret = (enum hab_status)call_imx_sip(FSL_SIP_HAB, FSL_SIP_HAB_ENTRY, 0, 0, 0); | 143 | ret = (enum hab_status)call_imx_sip(FSL_SIP_HAB, FSL_SIP_HAB_ENTRY, 0, 0, 0); |
138 | return ret; | 144 | return ret; |
139 | } | 145 | } |
140 | #endif | 146 | #endif |
141 | 147 | ||
142 | save_gd(); | 148 | save_gd(); |
143 | ret = hab_rvt_entry_func(); | 149 | ret = hab_rvt_entry_func(); |
144 | restore_gd(); | 150 | restore_gd(); |
145 | 151 | ||
146 | return ret; | 152 | return ret; |
147 | } | 153 | } |
148 | 154 | ||
149 | enum hab_status hab_rvt_exit(void) | 155 | enum hab_status hab_rvt_exit(void) |
150 | { | 156 | { |
151 | enum hab_status ret; | 157 | enum hab_status ret; |
152 | hab_rvt_exit_t *hab_rvt_exit_func; | 158 | hab_rvt_exit_t *hab_rvt_exit_func; |
153 | hab_rvt_exit_func = (hab_rvt_exit_t *)HAB_RVT_EXIT; | 159 | hab_rvt_exit_func = (hab_rvt_exit_t *)HAB_RVT_EXIT; |
154 | 160 | ||
155 | #if defined(CONFIG_ARM64) | 161 | #if defined(CONFIG_ARM64) |
156 | if (current_el() != 3) { | 162 | if (current_el() != 3) { |
157 | /* call sip */ | 163 | /* call sip */ |
158 | ret = (enum hab_status)call_imx_sip(FSL_SIP_HAB, FSL_SIP_HAB_EXIT, 0, 0, 0); | 164 | ret = (enum hab_status)call_imx_sip(FSL_SIP_HAB, FSL_SIP_HAB_EXIT, 0, 0, 0); |
159 | return ret; | 165 | return ret; |
160 | } | 166 | } |
161 | #endif | 167 | #endif |
162 | 168 | ||
163 | save_gd(); | 169 | save_gd(); |
164 | ret = hab_rvt_exit_func(); | 170 | ret = hab_rvt_exit_func(); |
165 | restore_gd(); | 171 | restore_gd(); |
166 | 172 | ||
167 | return ret; | 173 | return ret; |
168 | } | 174 | } |
169 | 175 | ||
170 | void hab_rvt_failsafe(void) | 176 | void hab_rvt_failsafe(void) |
171 | { | 177 | { |
172 | hab_rvt_failsafe_t *hab_rvt_failsafe_func; | 178 | hab_rvt_failsafe_t *hab_rvt_failsafe_func; |
173 | hab_rvt_failsafe_func = (hab_rvt_failsafe_t *)HAB_RVT_FAILSAFE; | 179 | hab_rvt_failsafe_func = (hab_rvt_failsafe_t *)HAB_RVT_FAILSAFE; |
174 | 180 | ||
175 | #if defined(CONFIG_ARM64) | 181 | #if defined(CONFIG_ARM64) |
176 | if (current_el() != 3) { | 182 | if (current_el() != 3) { |
177 | /* call sip */ | 183 | /* call sip */ |
178 | call_imx_sip(FSL_SIP_HAB, FSL_SIP_HAB_FAILSAFE, 0, 0, 0); | 184 | call_imx_sip(FSL_SIP_HAB, FSL_SIP_HAB_FAILSAFE, 0, 0, 0); |
179 | return; | 185 | return; |
180 | } | 186 | } |
181 | #endif | 187 | #endif |
182 | 188 | ||
183 | save_gd(); | 189 | save_gd(); |
184 | hab_rvt_failsafe_func(); | 190 | hab_rvt_failsafe_func(); |
185 | restore_gd(); | 191 | restore_gd(); |
186 | } | 192 | } |
187 | 193 | ||
188 | enum hab_status hab_rvt_check_target(enum hab_target type, const void *start, | 194 | enum hab_status hab_rvt_check_target(enum hab_target type, const void *start, |
189 | size_t bytes) | 195 | size_t bytes) |
190 | { | 196 | { |
191 | enum hab_status ret; | 197 | enum hab_status ret; |
192 | hab_rvt_check_target_t *hab_rvt_check_target_func; | 198 | hab_rvt_check_target_t *hab_rvt_check_target_func; |
193 | hab_rvt_check_target_func = (hab_rvt_check_target_t *)HAB_RVT_CHECK_TARGET; | 199 | hab_rvt_check_target_func = (hab_rvt_check_target_t *)HAB_RVT_CHECK_TARGET; |
194 | 200 | ||
195 | #if defined(CONFIG_ARM64) | 201 | #if defined(CONFIG_ARM64) |
196 | if (current_el() != 3) { | 202 | if (current_el() != 3) { |
197 | /* call sip */ | 203 | /* call sip */ |
198 | ret = (enum hab_status)call_imx_sip(FSL_SIP_HAB, FSL_SIP_HAB_CHECK_TARGET, (unsigned long)type, | 204 | ret = (enum hab_status)call_imx_sip(FSL_SIP_HAB, FSL_SIP_HAB_CHECK_TARGET, (unsigned long)type, |
199 | (unsigned long)start, (unsigned long)bytes); | 205 | (unsigned long)start, (unsigned long)bytes); |
200 | return ret; | 206 | return ret; |
201 | } | 207 | } |
202 | #endif | 208 | #endif |
203 | 209 | ||
204 | save_gd(); | 210 | save_gd(); |
205 | ret = hab_rvt_check_target_func(type, start, bytes); | 211 | ret = hab_rvt_check_target_func(type, start, bytes); |
206 | restore_gd(); | 212 | restore_gd(); |
207 | 213 | ||
208 | return ret; | 214 | return ret; |
209 | } | 215 | } |
210 | 216 | ||
211 | void *hab_rvt_authenticate_image(uint8_t cid, ptrdiff_t ivt_offset, | 217 | void *hab_rvt_authenticate_image(uint8_t cid, ptrdiff_t ivt_offset, |
212 | void **start, size_t *bytes, hab_loader_callback_f_t loader) | 218 | void **start, size_t *bytes, hab_loader_callback_f_t loader) |
213 | { | 219 | { |
214 | void *ret; | 220 | void *ret; |
215 | hab_rvt_authenticate_image_t *hab_rvt_authenticate_image_func; | 221 | hab_rvt_authenticate_image_t *hab_rvt_authenticate_image_func; |
216 | hab_rvt_authenticate_image_func = (hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE; | 222 | hab_rvt_authenticate_image_func = (hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE; |
217 | 223 | ||
218 | #if defined(CONFIG_ARM64) | 224 | #if defined(CONFIG_ARM64) |
219 | if (current_el() != 3) { | 225 | if (current_el() != 3) { |
220 | /* call sip */ | 226 | /* call sip */ |
221 | ret = (void *)call_imx_sip(FSL_SIP_HAB, FSL_SIP_HAB_AUTHENTICATE, (unsigned long)ivt_offset, | 227 | ret = (void *)call_imx_sip(FSL_SIP_HAB, FSL_SIP_HAB_AUTHENTICATE, (unsigned long)ivt_offset, |
222 | (unsigned long)start, (unsigned long)bytes); | 228 | (unsigned long)start, (unsigned long)bytes); |
223 | return ret; | 229 | return ret; |
224 | } | 230 | } |
225 | #endif | 231 | #endif |
226 | 232 | ||
227 | save_gd(); | 233 | save_gd(); |
228 | ret = hab_rvt_authenticate_image_func(cid, ivt_offset, start, bytes, loader); | 234 | ret = hab_rvt_authenticate_image_func(cid, ivt_offset, start, bytes, loader); |
229 | restore_gd(); | 235 | restore_gd(); |
230 | 236 | ||
231 | return ret; | 237 | return ret; |
232 | } | 238 | } |
233 | 239 | ||
234 | #if !defined(CONFIG_SPL_BUILD) | 240 | #if !defined(CONFIG_SPL_BUILD) |
235 | 241 | ||
236 | #define MAX_RECORD_BYTES (8*1024) /* 4 kbytes */ | 242 | #define MAX_RECORD_BYTES (8*1024) /* 4 kbytes */ |
237 | 243 | ||
238 | struct record { | 244 | struct record { |
239 | uint8_t tag; /* Tag */ | 245 | uint8_t tag; /* Tag */ |
240 | uint8_t len[2]; /* Length */ | 246 | uint8_t len[2]; /* Length */ |
241 | uint8_t par; /* Version */ | 247 | uint8_t par; /* Version */ |
242 | uint8_t contents[MAX_RECORD_BYTES];/* Record Data */ | 248 | uint8_t contents[MAX_RECORD_BYTES];/* Record Data */ |
243 | bool any_rec_flag; | 249 | bool any_rec_flag; |
244 | }; | 250 | }; |
245 | 251 | ||
246 | static char *rsn_str[] = { | 252 | static char *rsn_str[] = { |
247 | "RSN = HAB_RSN_ANY (0x00)\n", | 253 | "RSN = HAB_RSN_ANY (0x00)\n", |
248 | "RSN = HAB_ENG_FAIL (0x30)\n", | 254 | "RSN = HAB_ENG_FAIL (0x30)\n", |
249 | "RSN = HAB_INV_ADDRESS (0x22)\n", | 255 | "RSN = HAB_INV_ADDRESS (0x22)\n", |
250 | "RSN = HAB_INV_ASSERTION (0x0C)\n", | 256 | "RSN = HAB_INV_ASSERTION (0x0C)\n", |
251 | "RSN = HAB_INV_CALL (0x28)\n", | 257 | "RSN = HAB_INV_CALL (0x28)\n", |
252 | "RSN = HAB_INV_CERTIFICATE (0x21)\n", | 258 | "RSN = HAB_INV_CERTIFICATE (0x21)\n", |
253 | "RSN = HAB_INV_COMMAND (0x06)\n", | 259 | "RSN = HAB_INV_COMMAND (0x06)\n", |
254 | "RSN = HAB_INV_CSF (0x11)\n", | 260 | "RSN = HAB_INV_CSF (0x11)\n", |
255 | "RSN = HAB_INV_DCD (0x27)\n", | 261 | "RSN = HAB_INV_DCD (0x27)\n", |
256 | "RSN = HAB_INV_INDEX (0x0F)\n", | 262 | "RSN = HAB_INV_INDEX (0x0F)\n", |
257 | "RSN = HAB_INV_IVT (0x05)\n", | 263 | "RSN = HAB_INV_IVT (0x05)\n", |
258 | "RSN = HAB_INV_KEY (0x1D)\n", | 264 | "RSN = HAB_INV_KEY (0x1D)\n", |
259 | "RSN = HAB_INV_RETURN (0x1E)\n", | 265 | "RSN = HAB_INV_RETURN (0x1E)\n", |
260 | "RSN = HAB_INV_SIGNATURE (0x18)\n", | 266 | "RSN = HAB_INV_SIGNATURE (0x18)\n", |
261 | "RSN = HAB_INV_SIZE (0x17)\n", | 267 | "RSN = HAB_INV_SIZE (0x17)\n", |
262 | "RSN = HAB_MEM_FAIL (0x2E)\n", | 268 | "RSN = HAB_MEM_FAIL (0x2E)\n", |
263 | "RSN = HAB_OVR_COUNT (0x2B)\n", | 269 | "RSN = HAB_OVR_COUNT (0x2B)\n", |
264 | "RSN = HAB_OVR_STORAGE (0x2D)\n", | 270 | "RSN = HAB_OVR_STORAGE (0x2D)\n", |
265 | "RSN = HAB_UNS_ALGORITHM (0x12)\n", | 271 | "RSN = HAB_UNS_ALGORITHM (0x12)\n", |
266 | "RSN = HAB_UNS_COMMAND (0x03)\n", | 272 | "RSN = HAB_UNS_COMMAND (0x03)\n", |
267 | "RSN = HAB_UNS_ENGINE (0x0A)\n", | 273 | "RSN = HAB_UNS_ENGINE (0x0A)\n", |
268 | "RSN = HAB_UNS_ITEM (0x24)\n", | 274 | "RSN = HAB_UNS_ITEM (0x24)\n", |
269 | "RSN = HAB_UNS_KEY (0x1B)\n", | 275 | "RSN = HAB_UNS_KEY (0x1B)\n", |
270 | "RSN = HAB_UNS_PROTOCOL (0x14)\n", | 276 | "RSN = HAB_UNS_PROTOCOL (0x14)\n", |
271 | "RSN = HAB_UNS_STATE (0x09)\n", | 277 | "RSN = HAB_UNS_STATE (0x09)\n", |
272 | "RSN = INVALID\n", | 278 | "RSN = INVALID\n", |
273 | NULL | 279 | NULL |
274 | }; | 280 | }; |
275 | 281 | ||
276 | static char *sts_str[] = { | 282 | static char *sts_str[] = { |
277 | "STS = HAB_SUCCESS (0xF0)\n", | 283 | "STS = HAB_SUCCESS (0xF0)\n", |
278 | "STS = HAB_FAILURE (0x33)\n", | 284 | "STS = HAB_FAILURE (0x33)\n", |
279 | "STS = HAB_WARNING (0x69)\n", | 285 | "STS = HAB_WARNING (0x69)\n", |
280 | "STS = INVALID\n", | 286 | "STS = INVALID\n", |
281 | NULL | 287 | NULL |
282 | }; | 288 | }; |
283 | 289 | ||
284 | static char *eng_str[] = { | 290 | static char *eng_str[] = { |
285 | "ENG = HAB_ENG_ANY (0x00)\n", | 291 | "ENG = HAB_ENG_ANY (0x00)\n", |
286 | "ENG = HAB_ENG_SCC (0x03)\n", | 292 | "ENG = HAB_ENG_SCC (0x03)\n", |
287 | "ENG = HAB_ENG_RTIC (0x05)\n", | 293 | "ENG = HAB_ENG_RTIC (0x05)\n", |
288 | "ENG = HAB_ENG_SAHARA (0x06)\n", | 294 | "ENG = HAB_ENG_SAHARA (0x06)\n", |
289 | "ENG = HAB_ENG_CSU (0x0A)\n", | 295 | "ENG = HAB_ENG_CSU (0x0A)\n", |
290 | "ENG = HAB_ENG_SRTC (0x0C)\n", | 296 | "ENG = HAB_ENG_SRTC (0x0C)\n", |
291 | "ENG = HAB_ENG_DCP (0x1B)\n", | 297 | "ENG = HAB_ENG_DCP (0x1B)\n", |
292 | "ENG = HAB_ENG_CAAM (0x1D)\n", | 298 | "ENG = HAB_ENG_CAAM (0x1D)\n", |
293 | "ENG = HAB_ENG_SNVS (0x1E)\n", | 299 | "ENG = HAB_ENG_SNVS (0x1E)\n", |
294 | "ENG = HAB_ENG_OCOTP (0x21)\n", | 300 | "ENG = HAB_ENG_OCOTP (0x21)\n", |
295 | "ENG = HAB_ENG_DTCP (0x22)\n", | 301 | "ENG = HAB_ENG_DTCP (0x22)\n", |
296 | "ENG = HAB_ENG_ROM (0x36)\n", | 302 | "ENG = HAB_ENG_ROM (0x36)\n", |
297 | "ENG = HAB_ENG_HDCP (0x24)\n", | 303 | "ENG = HAB_ENG_HDCP (0x24)\n", |
298 | "ENG = HAB_ENG_RTL (0x77)\n", | 304 | "ENG = HAB_ENG_RTL (0x77)\n", |
299 | "ENG = HAB_ENG_SW (0xFF)\n", | 305 | "ENG = HAB_ENG_SW (0xFF)\n", |
300 | "ENG = INVALID\n", | 306 | "ENG = INVALID\n", |
301 | NULL | 307 | NULL |
302 | }; | 308 | }; |
303 | 309 | ||
304 | static char *ctx_str[] = { | 310 | static char *ctx_str[] = { |
305 | "CTX = HAB_CTX_ANY(0x00)\n", | 311 | "CTX = HAB_CTX_ANY(0x00)\n", |
306 | "CTX = HAB_CTX_FAB (0xFF)\n", | 312 | "CTX = HAB_CTX_FAB (0xFF)\n", |
307 | "CTX = HAB_CTX_ENTRY (0xE1)\n", | 313 | "CTX = HAB_CTX_ENTRY (0xE1)\n", |
308 | "CTX = HAB_CTX_TARGET (0x33)\n", | 314 | "CTX = HAB_CTX_TARGET (0x33)\n", |
309 | "CTX = HAB_CTX_AUTHENTICATE (0x0A)\n", | 315 | "CTX = HAB_CTX_AUTHENTICATE (0x0A)\n", |
310 | "CTX = HAB_CTX_DCD (0xDD)\n", | 316 | "CTX = HAB_CTX_DCD (0xDD)\n", |
311 | "CTX = HAB_CTX_CSF (0xCF)\n", | 317 | "CTX = HAB_CTX_CSF (0xCF)\n", |
312 | "CTX = HAB_CTX_COMMAND (0xC0)\n", | 318 | "CTX = HAB_CTX_COMMAND (0xC0)\n", |
313 | "CTX = HAB_CTX_AUT_DAT (0xDB)\n", | 319 | "CTX = HAB_CTX_AUT_DAT (0xDB)\n", |
314 | "CTX = HAB_CTX_ASSERT (0xA0)\n", | 320 | "CTX = HAB_CTX_ASSERT (0xA0)\n", |
315 | "CTX = HAB_CTX_EXIT (0xEE)\n", | 321 | "CTX = HAB_CTX_EXIT (0xEE)\n", |
316 | "CTX = INVALID\n", | 322 | "CTX = INVALID\n", |
317 | NULL | 323 | NULL |
318 | }; | 324 | }; |
319 | 325 | ||
320 | static uint8_t hab_statuses[5] = { | 326 | static uint8_t hab_statuses[5] = { |
321 | HAB_STS_ANY, | 327 | HAB_STS_ANY, |
322 | HAB_FAILURE, | 328 | HAB_FAILURE, |
323 | HAB_WARNING, | 329 | HAB_WARNING, |
324 | HAB_SUCCESS, | 330 | HAB_SUCCESS, |
325 | -1 | 331 | -1 |
326 | }; | 332 | }; |
327 | 333 | ||
328 | static uint8_t hab_reasons[26] = { | 334 | static uint8_t hab_reasons[26] = { |
329 | HAB_RSN_ANY, | 335 | HAB_RSN_ANY, |
330 | HAB_ENG_FAIL, | 336 | HAB_ENG_FAIL, |
331 | HAB_INV_ADDRESS, | 337 | HAB_INV_ADDRESS, |
332 | HAB_INV_ASSERTION, | 338 | HAB_INV_ASSERTION, |
333 | HAB_INV_CALL, | 339 | HAB_INV_CALL, |
334 | HAB_INV_CERTIFICATE, | 340 | HAB_INV_CERTIFICATE, |
335 | HAB_INV_COMMAND, | 341 | HAB_INV_COMMAND, |
336 | HAB_INV_CSF, | 342 | HAB_INV_CSF, |
337 | HAB_INV_DCD, | 343 | HAB_INV_DCD, |
338 | HAB_INV_INDEX, | 344 | HAB_INV_INDEX, |
339 | HAB_INV_IVT, | 345 | HAB_INV_IVT, |
340 | HAB_INV_KEY, | 346 | HAB_INV_KEY, |
341 | HAB_INV_RETURN, | 347 | HAB_INV_RETURN, |
342 | HAB_INV_SIGNATURE, | 348 | HAB_INV_SIGNATURE, |
343 | HAB_INV_SIZE, | 349 | HAB_INV_SIZE, |
344 | HAB_MEM_FAIL, | 350 | HAB_MEM_FAIL, |
345 | HAB_OVR_COUNT, | 351 | HAB_OVR_COUNT, |
346 | HAB_OVR_STORAGE, | 352 | HAB_OVR_STORAGE, |
347 | HAB_UNS_ALGORITHM, | 353 | HAB_UNS_ALGORITHM, |
348 | HAB_UNS_COMMAND, | 354 | HAB_UNS_COMMAND, |
349 | HAB_UNS_ENGINE, | 355 | HAB_UNS_ENGINE, |
350 | HAB_UNS_ITEM, | 356 | HAB_UNS_ITEM, |
351 | HAB_UNS_KEY, | 357 | HAB_UNS_KEY, |
352 | HAB_UNS_PROTOCOL, | 358 | HAB_UNS_PROTOCOL, |
353 | HAB_UNS_STATE, | 359 | HAB_UNS_STATE, |
354 | -1 | 360 | -1 |
355 | }; | 361 | }; |
356 | 362 | ||
357 | static uint8_t hab_contexts[12] = { | 363 | static uint8_t hab_contexts[12] = { |
358 | HAB_CTX_ANY, | 364 | HAB_CTX_ANY, |
359 | HAB_CTX_FAB, | 365 | HAB_CTX_FAB, |
360 | HAB_CTX_ENTRY, | 366 | HAB_CTX_ENTRY, |
361 | HAB_CTX_TARGET, | 367 | HAB_CTX_TARGET, |
362 | HAB_CTX_AUTHENTICATE, | 368 | HAB_CTX_AUTHENTICATE, |
363 | HAB_CTX_DCD, | 369 | HAB_CTX_DCD, |
364 | HAB_CTX_CSF, | 370 | HAB_CTX_CSF, |
365 | HAB_CTX_COMMAND, | 371 | HAB_CTX_COMMAND, |
366 | HAB_CTX_AUT_DAT, | 372 | HAB_CTX_AUT_DAT, |
367 | HAB_CTX_ASSERT, | 373 | HAB_CTX_ASSERT, |
368 | HAB_CTX_EXIT, | 374 | HAB_CTX_EXIT, |
369 | -1 | 375 | -1 |
370 | }; | 376 | }; |
371 | 377 | ||
372 | static uint8_t hab_engines[16] = { | 378 | static uint8_t hab_engines[16] = { |
373 | HAB_ENG_ANY, | 379 | HAB_ENG_ANY, |
374 | HAB_ENG_SCC, | 380 | HAB_ENG_SCC, |
375 | HAB_ENG_RTIC, | 381 | HAB_ENG_RTIC, |
376 | HAB_ENG_SAHARA, | 382 | HAB_ENG_SAHARA, |
377 | HAB_ENG_CSU, | 383 | HAB_ENG_CSU, |
378 | HAB_ENG_SRTC, | 384 | HAB_ENG_SRTC, |
379 | HAB_ENG_DCP, | 385 | HAB_ENG_DCP, |
380 | HAB_ENG_CAAM, | 386 | HAB_ENG_CAAM, |
381 | HAB_ENG_SNVS, | 387 | HAB_ENG_SNVS, |
382 | HAB_ENG_OCOTP, | 388 | HAB_ENG_OCOTP, |
383 | HAB_ENG_DTCP, | 389 | HAB_ENG_DTCP, |
384 | HAB_ENG_ROM, | 390 | HAB_ENG_ROM, |
385 | HAB_ENG_HDCP, | 391 | HAB_ENG_HDCP, |
386 | HAB_ENG_RTL, | 392 | HAB_ENG_RTL, |
387 | HAB_ENG_SW, | 393 | HAB_ENG_SW, |
388 | -1 | 394 | -1 |
389 | }; | 395 | }; |
390 | 396 | ||
391 | static inline uint8_t get_idx(uint8_t *list, uint8_t tgt) | 397 | static inline uint8_t get_idx(uint8_t *list, uint8_t tgt) |
392 | { | 398 | { |
393 | uint8_t idx = 0; | 399 | uint8_t idx = 0; |
394 | uint8_t element = list[idx]; | 400 | uint8_t element = list[idx]; |
395 | while (element != -1) { | 401 | while (element != -1) { |
396 | if (element == tgt) | 402 | if (element == tgt) |
397 | return idx; | 403 | return idx; |
398 | element = list[++idx]; | 404 | element = list[++idx]; |
399 | } | 405 | } |
400 | return -1; | 406 | return -1; |
401 | } | 407 | } |
402 | 408 | ||
403 | static void process_event_record(uint8_t *event_data, size_t bytes) | 409 | static void process_event_record(uint8_t *event_data, size_t bytes) |
404 | { | 410 | { |
405 | struct record *rec = (struct record *)event_data; | 411 | struct record *rec = (struct record *)event_data; |
406 | 412 | ||
407 | printf("\n\n%s", sts_str[get_idx(hab_statuses, rec->contents[0])]); | 413 | printf("\n\n%s", sts_str[get_idx(hab_statuses, rec->contents[0])]); |
408 | printf("%s", rsn_str[get_idx(hab_reasons, rec->contents[1])]); | 414 | printf("%s", rsn_str[get_idx(hab_reasons, rec->contents[1])]); |
409 | printf("%s", ctx_str[get_idx(hab_contexts, rec->contents[2])]); | 415 | printf("%s", ctx_str[get_idx(hab_contexts, rec->contents[2])]); |
410 | printf("%s", eng_str[get_idx(hab_engines, rec->contents[3])]); | 416 | printf("%s", eng_str[get_idx(hab_engines, rec->contents[3])]); |
411 | } | 417 | } |
412 | 418 | ||
413 | static void display_event(uint8_t *event_data, size_t bytes) | 419 | static void display_event(uint8_t *event_data, size_t bytes) |
414 | { | 420 | { |
415 | uint32_t i; | 421 | uint32_t i; |
416 | 422 | ||
417 | if (!(event_data && bytes > 0)) | 423 | if (!(event_data && bytes > 0)) |
418 | return; | 424 | return; |
419 | 425 | ||
420 | for (i = 0; i < bytes; i++) { | 426 | for (i = 0; i < bytes; i++) { |
421 | if (i == 0) | 427 | if (i == 0) |
422 | printf("\t0x%02x", event_data[i]); | 428 | printf("\t0x%02x", event_data[i]); |
423 | else if ((i % 8) == 0) | 429 | else if ((i % 8) == 0) |
424 | printf("\n\t0x%02x", event_data[i]); | 430 | printf("\n\t0x%02x", event_data[i]); |
425 | else | 431 | else |
426 | printf(" 0x%02x", event_data[i]); | 432 | printf(" 0x%02x", event_data[i]); |
427 | } | 433 | } |
428 | 434 | ||
429 | process_event_record(event_data, bytes); | 435 | process_event_record(event_data, bytes); |
430 | } | 436 | } |
431 | 437 | ||
432 | static int get_hab_status(void) | 438 | static int get_hab_status(void) |
433 | { | 439 | { |
434 | uint32_t index = 0; /* Loop index */ | 440 | uint32_t index = 0; /* Loop index */ |
435 | uint8_t event_data[128]; /* Event data buffer */ | 441 | uint8_t event_data[128]; /* Event data buffer */ |
436 | size_t bytes = sizeof(event_data); /* Event size in bytes */ | 442 | size_t bytes = sizeof(event_data); /* Event size in bytes */ |
437 | enum hab_config config = 0; | 443 | enum hab_config config = 0; |
438 | enum hab_state state = 0; | 444 | enum hab_state state = 0; |
439 | 445 | ||
440 | if (imx_hab_is_enabled()) | 446 | if (imx_hab_is_enabled()) |
441 | puts("\nSecure boot enabled\n"); | 447 | puts("\nSecure boot enabled\n"); |
442 | else | 448 | else |
443 | puts("\nSecure boot disabled\n"); | 449 | puts("\nSecure boot disabled\n"); |
444 | 450 | ||
445 | /* Check HAB status */ | 451 | /* Check HAB status */ |
446 | if (hab_rvt_report_status(&config, &state) != HAB_SUCCESS) { | 452 | if (hab_rvt_report_status(&config, &state) != HAB_SUCCESS) { |
447 | printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n", | 453 | printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n", |
448 | config, state); | 454 | config, state); |
449 | 455 | ||
450 | /* Display HAB events */ | 456 | /* Display HAB events */ |
451 | while (hab_rvt_report_event(HAB_STS_ANY, index, event_data, | 457 | while (hab_rvt_report_event(HAB_STS_ANY, index, event_data, |
452 | &bytes) == HAB_SUCCESS) { | 458 | &bytes) == HAB_SUCCESS) { |
453 | puts("\n"); | 459 | puts("\n"); |
454 | printf("--------- HAB Event %d -----------------\n", | 460 | printf("--------- HAB Event %d -----------------\n", |
455 | index + 1); | 461 | index + 1); |
456 | puts("event data:\n"); | 462 | puts("event data:\n"); |
457 | display_event(event_data, bytes); | 463 | display_event(event_data, bytes); |
458 | puts("\n"); | 464 | puts("\n"); |
459 | bytes = sizeof(event_data); | 465 | bytes = sizeof(event_data); |
460 | index++; | 466 | index++; |
461 | } | 467 | } |
462 | } | 468 | } |
463 | /* Display message if no HAB events are found */ | 469 | /* Display message if no HAB events are found */ |
464 | else { | 470 | else { |
465 | printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n", | 471 | printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n", |
466 | config, state); | 472 | config, state); |
467 | puts("No HAB Events Found!\n\n"); | 473 | puts("No HAB Events Found!\n\n"); |
468 | } | 474 | } |
469 | return 0; | 475 | return 0; |
470 | } | 476 | } |
471 | 477 | ||
478 | #ifdef CONFIG_MX7ULP | ||
479 | |||
480 | static int get_record_len(struct record *rec) | ||
481 | { | ||
482 | return (size_t)((rec->len[0] << 8) + (rec->len[1])); | ||
483 | } | ||
484 | |||
485 | static int get_hab_status_m4(void) | ||
486 | { | ||
487 | unsigned int index = 0; | ||
488 | uint8_t event_data[128]; | ||
489 | size_t record_len, offset = 0; | ||
490 | enum hab_config config = 0; | ||
491 | enum hab_state state = 0; | ||
492 | |||
493 | if (imx_hab_is_enabled()) | ||
494 | puts("\nSecure boot enabled\n"); | ||
495 | else | ||
496 | puts("\nSecure boot disabled\n"); | ||
497 | |||
498 | /* | ||
499 | * HAB in both A7 and M4 gather the security state | ||
500 | * and configuration of the chip from | ||
501 | * shared SNVS module | ||
502 | */ | ||
503 | hab_rvt_report_status(&config, &state); | ||
504 | printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n", | ||
505 | config, state); | ||
506 | |||
507 | struct record *rec = (struct record *)(HAB_M4_PERSISTENT_START); | ||
508 | |||
509 | record_len = get_record_len(rec); | ||
510 | |||
511 | /* Check if HAB persistent memory is valid */ | ||
512 | if (rec->tag != HAB_TAG_EVT_DEF || | ||
513 | record_len != sizeof(struct evt_def) || | ||
514 | (rec->par & HAB_MAJ_MASK) != HAB_MAJ_VER) { | ||
515 | puts("\nERROR: Invalid HAB persistent memory\n"); | ||
516 | return 1; | ||
517 | } | ||
518 | |||
519 | /* Parse events in HAB M4 persistent memory region */ | ||
520 | while (offset < HAB_M4_PERSISTENT_BYTES) { | ||
521 | rec = (struct record *)(HAB_M4_PERSISTENT_START + offset); | ||
522 | |||
523 | record_len = get_record_len(rec); | ||
524 | |||
525 | if (rec->tag == HAB_TAG_EVT) { | ||
526 | memcpy(&event_data, rec, record_len); | ||
527 | puts("\n"); | ||
528 | printf("--------- HAB Event %d -----------------\n", | ||
529 | index + 1); | ||
530 | puts("event data:\n"); | ||
531 | display_event(event_data, record_len); | ||
532 | puts("\n"); | ||
533 | index++; | ||
534 | } | ||
535 | |||
536 | offset += record_len; | ||
537 | |||
538 | /* Ensure all records start on a word boundary */ | ||
539 | if ((offset % 4) != 0) | ||
540 | offset = offset + (4 - (offset % 4)); | ||
541 | } | ||
542 | |||
543 | if (!index) | ||
544 | puts("No HAB Events Found!\n\n"); | ||
545 | |||
546 | return 0; | ||
547 | } | ||
548 | #endif | ||
549 | |||
472 | static int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, | 550 | static int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, |
473 | char * const argv[]) | 551 | char * const argv[]) |
474 | { | 552 | { |
553 | #ifdef CONFIG_MX7ULP | ||
554 | if ((argc > 2)) { | ||
555 | cmd_usage(cmdtp); | ||
556 | return 1; | ||
557 | } | ||
558 | |||
559 | if (strcmp("m4", argv[1]) == 0) | ||
560 | get_hab_status_m4(); | ||
561 | else | ||
562 | get_hab_status(); | ||
563 | #else | ||
475 | if ((argc != 1)) { | 564 | if ((argc != 1)) { |
476 | cmd_usage(cmdtp); | 565 | cmd_usage(cmdtp); |
477 | return 1; | 566 | return 1; |
478 | } | 567 | } |
479 | 568 | ||
480 | get_hab_status(); | 569 | get_hab_status(); |
570 | #endif | ||
481 | 571 | ||
482 | return 0; | 572 | return 0; |
483 | } | 573 | } |
484 | 574 | ||
485 | static int do_authenticate_image(cmd_tbl_t *cmdtp, int flag, int argc, | 575 | static int do_authenticate_image(cmd_tbl_t *cmdtp, int flag, int argc, |
486 | char * const argv[]) | 576 | char * const argv[]) |
487 | { | 577 | { |
488 | ulong addr, length, ivt_offset; | 578 | ulong addr, length, ivt_offset; |
489 | int rcode = 0; | 579 | int rcode = 0; |
490 | 580 | ||
491 | if (argc < 4) | 581 | if (argc < 4) |
492 | return CMD_RET_USAGE; | 582 | return CMD_RET_USAGE; |
493 | 583 | ||
494 | addr = simple_strtoul(argv[1], NULL, 16); | 584 | addr = simple_strtoul(argv[1], NULL, 16); |
495 | length = simple_strtoul(argv[2], NULL, 16); | 585 | length = simple_strtoul(argv[2], NULL, 16); |
496 | ivt_offset = simple_strtoul(argv[3], NULL, 16); | 586 | ivt_offset = simple_strtoul(argv[3], NULL, 16); |
497 | 587 | ||
498 | rcode = imx_hab_authenticate_image(addr, length, ivt_offset); | 588 | rcode = imx_hab_authenticate_image(addr, length, ivt_offset); |
499 | if (rcode == 0) | 589 | if (rcode == 0) |
500 | rcode = CMD_RET_SUCCESS; | 590 | rcode = CMD_RET_SUCCESS; |
501 | else | 591 | else |
502 | rcode = CMD_RET_FAILURE; | 592 | rcode = CMD_RET_FAILURE; |
503 | 593 | ||
504 | return rcode; | 594 | return rcode; |
505 | } | 595 | } |
506 | 596 | ||
507 | static int do_hab_failsafe(cmd_tbl_t *cmdtp, int flag, int argc, | 597 | static int do_hab_failsafe(cmd_tbl_t *cmdtp, int flag, int argc, |
508 | char * const argv[]) | 598 | char * const argv[]) |
509 | { | 599 | { |
510 | if (argc != 1) { | 600 | if (argc != 1) { |
511 | cmd_usage(cmdtp); | 601 | cmd_usage(cmdtp); |
512 | return 1; | 602 | return 1; |
513 | } | 603 | } |
514 | 604 | ||
515 | hab_rvt_failsafe(); | 605 | hab_rvt_failsafe(); |
516 | 606 | ||
517 | return 0; | 607 | return 0; |
518 | } | 608 | } |
519 | 609 | ||
610 | #ifdef CONFIG_MX7ULP | ||
520 | U_BOOT_CMD( | 611 | U_BOOT_CMD( |
612 | hab_status, CONFIG_SYS_MAXARGS, 2, do_hab_status, | ||
613 | "display HAB status and events", | ||
614 | "hab_status - A7 HAB event and status\n" | ||
615 | "hab_status m4 - M4 HAB event and status" | ||
616 | ); | ||
617 | #else | ||
618 | U_BOOT_CMD( | ||
521 | hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status, | 619 | hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status, |
522 | "display HAB status", | 620 | "display HAB status", |
523 | "" | 621 | "" |
524 | ); | 622 | ); |
623 | #endif | ||
525 | 624 | ||
526 | U_BOOT_CMD( | 625 | U_BOOT_CMD( |
527 | hab_auth_img, 4, 0, do_authenticate_image, | 626 | hab_auth_img, 4, 0, do_authenticate_image, |
528 | "authenticate image via HAB", | 627 | "authenticate image via HAB", |
529 | "addr length ivt_offset\n" | 628 | "addr length ivt_offset\n" |
530 | "addr - image hex address\n" | 629 | "addr - image hex address\n" |
531 | "length - image hex length\n" | 630 | "length - image hex length\n" |
532 | "ivt_offset - hex offset of IVT in the image" | 631 | "ivt_offset - hex offset of IVT in the image" |
533 | ); | 632 | ); |
534 | 633 | ||
535 | U_BOOT_CMD( | 634 | U_BOOT_CMD( |
536 | hab_failsafe, CONFIG_SYS_MAXARGS, 1, do_hab_failsafe, | 635 | hab_failsafe, CONFIG_SYS_MAXARGS, 1, do_hab_failsafe, |
537 | "run BootROM failsafe routine", | 636 | "run BootROM failsafe routine", |
538 | "" | 637 | "" |
539 | ); | 638 | ); |
540 | 639 | ||
541 | #endif /* !defined(CONFIG_SPL_BUILD) */ | 640 | #endif /* !defined(CONFIG_SPL_BUILD) */ |
542 | 641 | ||
543 | /* Get CSF Header length */ | 642 | /* Get CSF Header length */ |
544 | static int get_hab_hdr_len(struct hab_hdr *hdr) | 643 | static int get_hab_hdr_len(struct hab_hdr *hdr) |
545 | { | 644 | { |
546 | return (size_t)((hdr->len[0] << 8) + (hdr->len[1])); | 645 | return (size_t)((hdr->len[0] << 8) + (hdr->len[1])); |
547 | } | 646 | } |
548 | 647 | ||
549 | /* Check whether addr lies between start and | 648 | /* Check whether addr lies between start and |
550 | * end and is within the length of the image | 649 | * end and is within the length of the image |
551 | */ | 650 | */ |
552 | static int chk_bounds(u8 *addr, size_t bytes, u8 *start, u8 *end) | 651 | static int chk_bounds(u8 *addr, size_t bytes, u8 *start, u8 *end) |
553 | { | 652 | { |
554 | size_t csf_size = (size_t)((end + 1) - addr); | 653 | size_t csf_size = (size_t)((end + 1) - addr); |
555 | 654 | ||
556 | return (addr && (addr >= start) && (addr <= end) && | 655 | return (addr && (addr >= start) && (addr <= end) && |
557 | (csf_size >= bytes)); | 656 | (csf_size >= bytes)); |
558 | } | 657 | } |
559 | 658 | ||
560 | /* Get Length of each command in CSF */ | 659 | /* Get Length of each command in CSF */ |
561 | static int get_csf_cmd_hdr_len(u8 *csf_hdr) | 660 | static int get_csf_cmd_hdr_len(u8 *csf_hdr) |
562 | { | 661 | { |
563 | if (*csf_hdr == HAB_CMD_HDR) | 662 | if (*csf_hdr == HAB_CMD_HDR) |
564 | return sizeof(struct hab_hdr); | 663 | return sizeof(struct hab_hdr); |
565 | 664 | ||
566 | return get_hab_hdr_len((struct hab_hdr *)csf_hdr); | 665 | return get_hab_hdr_len((struct hab_hdr *)csf_hdr); |
567 | } | 666 | } |
568 | 667 | ||
569 | /* Check if CSF is valid */ | 668 | /* Check if CSF is valid */ |
570 | static bool csf_is_valid(struct ivt *ivt, ulong start_addr, size_t bytes) | 669 | static bool csf_is_valid(struct ivt *ivt, ulong start_addr, size_t bytes) |
571 | { | 670 | { |
572 | u8 *start = (u8 *)start_addr; | 671 | u8 *start = (u8 *)start_addr; |
573 | u8 *csf_hdr; | 672 | u8 *csf_hdr; |
574 | u8 *end; | 673 | u8 *end; |
575 | 674 | ||
576 | size_t csf_hdr_len; | 675 | size_t csf_hdr_len; |
577 | size_t cmd_hdr_len; | 676 | size_t cmd_hdr_len; |
578 | size_t offset = 0; | 677 | size_t offset = 0; |
579 | 678 | ||
580 | if (bytes != 0) | 679 | if (bytes != 0) |
581 | end = start + bytes - 1; | 680 | end = start + bytes - 1; |
582 | else | 681 | else |
583 | end = start; | 682 | end = start; |
584 | 683 | ||
585 | /* Verify if CSF pointer content is zero */ | 684 | /* Verify if CSF pointer content is zero */ |
586 | if (!ivt->csf) { | 685 | if (!ivt->csf) { |
587 | puts("Error: CSF pointer is NULL\n"); | 686 | puts("Error: CSF pointer is NULL\n"); |
588 | return false; | 687 | return false; |
589 | } | 688 | } |
590 | 689 | ||
591 | csf_hdr = (u8 *)(ulong)ivt->csf; | 690 | csf_hdr = (u8 *)(ulong)ivt->csf; |
592 | 691 | ||
593 | /* Verify if CSF Header exist */ | 692 | /* Verify if CSF Header exist */ |
594 | if (*csf_hdr != HAB_CMD_HDR) { | 693 | if (*csf_hdr != HAB_CMD_HDR) { |
595 | puts("Error: CSF header command not found\n"); | 694 | puts("Error: CSF header command not found\n"); |
596 | return false; | 695 | return false; |
597 | } | 696 | } |
598 | 697 | ||
599 | csf_hdr_len = get_hab_hdr_len((struct hab_hdr *)csf_hdr); | 698 | csf_hdr_len = get_hab_hdr_len((struct hab_hdr *)csf_hdr); |
600 | 699 | ||
601 | /* Check if the CSF lies within the image bounds */ | 700 | /* Check if the CSF lies within the image bounds */ |
602 | if (!chk_bounds(csf_hdr, csf_hdr_len, start, end)) { | 701 | if (!chk_bounds(csf_hdr, csf_hdr_len, start, end)) { |
603 | puts("Error: CSF lies outside the image bounds\n"); | 702 | puts("Error: CSF lies outside the image bounds\n"); |
604 | return false; | 703 | return false; |
605 | } | 704 | } |
606 | 705 | ||
607 | do { | 706 | do { |
608 | struct hab_hdr *cmd; | 707 | struct hab_hdr *cmd; |
609 | 708 | ||
610 | cmd = (struct hab_hdr *)&csf_hdr[offset]; | 709 | cmd = (struct hab_hdr *)&csf_hdr[offset]; |
611 | 710 | ||
612 | switch (cmd->tag) { | 711 | switch (cmd->tag) { |
613 | case (HAB_CMD_WRT_DAT): | 712 | case (HAB_CMD_WRT_DAT): |
614 | puts("Error: Deprecated write command found\n"); | 713 | puts("Error: Deprecated write command found\n"); |
615 | return false; | 714 | return false; |
616 | case (HAB_CMD_CHK_DAT): | 715 | case (HAB_CMD_CHK_DAT): |
617 | puts("Error: Deprecated check command found\n"); | 716 | puts("Error: Deprecated check command found\n"); |
618 | return false; | 717 | return false; |
619 | case (HAB_CMD_SET): | 718 | case (HAB_CMD_SET): |
620 | if (cmd->par == HAB_PAR_MID) { | 719 | if (cmd->par == HAB_PAR_MID) { |
621 | puts("Error: Deprecated Set MID command found\n"); | 720 | puts("Error: Deprecated Set MID command found\n"); |
622 | return false; | 721 | return false; |
623 | } | 722 | } |
624 | default: | 723 | default: |
625 | break; | 724 | break; |
626 | } | 725 | } |
627 | 726 | ||
628 | cmd_hdr_len = get_csf_cmd_hdr_len(&csf_hdr[offset]); | 727 | cmd_hdr_len = get_csf_cmd_hdr_len(&csf_hdr[offset]); |
629 | if (!cmd_hdr_len) { | 728 | if (!cmd_hdr_len) { |
630 | puts("Error: Invalid command length\n"); | 729 | puts("Error: Invalid command length\n"); |
631 | return false; | 730 | return false; |
632 | } | 731 | } |
633 | offset += cmd_hdr_len; | 732 | offset += cmd_hdr_len; |
634 | 733 | ||
635 | } while (offset < csf_hdr_len); | 734 | } while (offset < csf_hdr_len); |
636 | 735 | ||
637 | return true; | 736 | return true; |
638 | } | 737 | } |
639 | 738 | ||
640 | /* | 739 | /* |
641 | * Validate IVT structure of the image being authenticated | 740 | * Validate IVT structure of the image being authenticated |
642 | */ | 741 | */ |
643 | static int validate_ivt(struct ivt *ivt_initial) | 742 | static int validate_ivt(struct ivt *ivt_initial) |
644 | { | 743 | { |
645 | struct ivt_header *ivt_hdr = &ivt_initial->hdr; | 744 | struct ivt_header *ivt_hdr = &ivt_initial->hdr; |
646 | 745 | ||
647 | if ((ulong)ivt_initial & 0x3) { | 746 | if ((ulong)ivt_initial & 0x3) { |
648 | puts("Error: Image's start address is not 4 byte aligned\n"); | 747 | puts("Error: Image's start address is not 4 byte aligned\n"); |
649 | return 0; | 748 | return 0; |
650 | } | 749 | } |
651 | 750 | ||
652 | /* Check IVT fields before allowing authentication */ | 751 | /* Check IVT fields before allowing authentication */ |
653 | if ((!verify_ivt_header(ivt_hdr)) && \ | 752 | if ((!verify_ivt_header(ivt_hdr)) && \ |
654 | (ivt_initial->entry != 0x0) && \ | 753 | (ivt_initial->entry != 0x0) && \ |
655 | (ivt_initial->reserved1 == 0x0) && \ | 754 | (ivt_initial->reserved1 == 0x0) && \ |
656 | (ivt_initial->self == \ | 755 | (ivt_initial->self == \ |
657 | (uint32_t)((ulong)ivt_initial & 0xffffffff)) && \ | 756 | (uint32_t)((ulong)ivt_initial & 0xffffffff)) && \ |
658 | (ivt_initial->csf != 0x0) && \ | 757 | (ivt_initial->csf != 0x0) && \ |
659 | (ivt_initial->reserved2 == 0x0)) { | 758 | (ivt_initial->reserved2 == 0x0)) { |
660 | /* Report boot failure if DCD pointer is found in IVT */ | 759 | /* Report boot failure if DCD pointer is found in IVT */ |
661 | if (ivt_initial->dcd != 0x0) | 760 | if (ivt_initial->dcd != 0x0) |
662 | puts("Error: DCD pointer must be 0\n"); | 761 | puts("Error: DCD pointer must be 0\n"); |
663 | else | 762 | else |
664 | return 1; | 763 | return 1; |
665 | } | 764 | } |
666 | 765 | ||
667 | puts("Error: Invalid IVT structure\n"); | 766 | puts("Error: Invalid IVT structure\n"); |
668 | puts("\nAllowed IVT structure:\n"); | 767 | puts("\nAllowed IVT structure:\n"); |
669 | puts("IVT HDR = 0x4X2000D1\n"); | 768 | puts("IVT HDR = 0x4X2000D1\n"); |
670 | puts("IVT ENTRY = 0xXXXXXXXX\n"); | 769 | puts("IVT ENTRY = 0xXXXXXXXX\n"); |
671 | puts("IVT RSV1 = 0x0\n"); | 770 | puts("IVT RSV1 = 0x0\n"); |
672 | puts("IVT DCD = 0x0\n"); /* Recommended */ | 771 | puts("IVT DCD = 0x0\n"); /* Recommended */ |
673 | puts("IVT BOOT_DATA = 0xXXXXXXXX\n"); /* Commonly 0x0 */ | 772 | puts("IVT BOOT_DATA = 0xXXXXXXXX\n"); /* Commonly 0x0 */ |
674 | puts("IVT SELF = 0xXXXXXXXX\n"); /* = ddr_start + ivt_offset */ | 773 | puts("IVT SELF = 0xXXXXXXXX\n"); /* = ddr_start + ivt_offset */ |
675 | puts("IVT CSF = 0xXXXXXXXX\n"); | 774 | puts("IVT CSF = 0xXXXXXXXX\n"); |
676 | puts("IVT RSV2 = 0x0\n"); | 775 | puts("IVT RSV2 = 0x0\n"); |
677 | 776 | ||
678 | /* Invalid IVT structure */ | 777 | /* Invalid IVT structure */ |
679 | return 0; | 778 | return 0; |
680 | } | 779 | } |
681 | 780 | ||
682 | bool imx_hab_is_enabled(void) | 781 | bool imx_hab_is_enabled(void) |
683 | { | 782 | { |
684 | struct imx_sec_config_fuse_t *fuse = | 783 | struct imx_sec_config_fuse_t *fuse = |
685 | (struct imx_sec_config_fuse_t *)&imx_sec_config_fuse; | 784 | (struct imx_sec_config_fuse_t *)&imx_sec_config_fuse; |
686 | uint32_t reg; | 785 | uint32_t reg; |
687 | int ret; | 786 | int ret; |
688 | 787 | ||
689 | ret = fuse_read(fuse->bank, fuse->word, ®); | 788 | ret = fuse_read(fuse->bank, fuse->word, ®); |
690 | if (ret) { | 789 | if (ret) { |
691 | puts("\nSecure boot fuse read error\n"); | 790 | puts("\nSecure boot fuse read error\n"); |
692 | return ret; | 791 | return ret; |
693 | } | 792 | } |
694 | 793 | ||
695 | return (reg & IS_HAB_ENABLED_BIT) == IS_HAB_ENABLED_BIT; | 794 | return (reg & IS_HAB_ENABLED_BIT) == IS_HAB_ENABLED_BIT; |
696 | } | 795 | } |
697 | 796 | ||
698 | int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size, | 797 | int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size, |
699 | uint32_t ivt_offset) | 798 | uint32_t ivt_offset) |
700 | { | 799 | { |
701 | ulong load_addr = 0; | 800 | ulong load_addr = 0; |
702 | size_t bytes; | 801 | size_t bytes; |
703 | ulong ivt_addr = 0; | 802 | ulong ivt_addr = 0; |
704 | int result = 1; | 803 | int result = 1; |
705 | ulong start; | 804 | ulong start; |
706 | struct ivt *ivt; | 805 | struct ivt *ivt; |
707 | enum hab_status status; | 806 | enum hab_status status; |
708 | 807 | ||
709 | if (!imx_hab_is_enabled()) | 808 | if (!imx_hab_is_enabled()) |
710 | puts("hab fuse not enabled\n"); | 809 | puts("hab fuse not enabled\n"); |
711 | 810 | ||
712 | printf("\nAuthenticate image from DDR location 0x%x...\n", | 811 | printf("\nAuthenticate image from DDR location 0x%x...\n", |
713 | ddr_start); | 812 | ddr_start); |
714 | 813 | ||
715 | hab_caam_clock_enable(1); | 814 | hab_caam_clock_enable(1); |
716 | 815 | ||
717 | /* Calculate IVT address header */ | 816 | /* Calculate IVT address header */ |
718 | ivt_addr = (ulong) (ddr_start + ivt_offset); | 817 | ivt_addr = (ulong) (ddr_start + ivt_offset); |
719 | ivt = (struct ivt *)ivt_addr; | 818 | ivt = (struct ivt *)ivt_addr; |
720 | 819 | ||
721 | /* Verify IVT header bugging out on error */ | 820 | /* Verify IVT header bugging out on error */ |
722 | if (!validate_ivt(ivt)) | 821 | if (!validate_ivt(ivt)) |
723 | goto hab_authentication_exit; | 822 | goto hab_authentication_exit; |
724 | 823 | ||
725 | start = ddr_start; | 824 | start = ddr_start; |
726 | bytes = image_size; | 825 | bytes = image_size; |
727 | 826 | ||
728 | /* Verify CSF */ | 827 | /* Verify CSF */ |
729 | if (!csf_is_valid(ivt, start, bytes)) | 828 | if (!csf_is_valid(ivt, start, bytes)) |
730 | goto hab_authentication_exit; | 829 | goto hab_authentication_exit; |
731 | 830 | ||
732 | if (hab_rvt_entry() != HAB_SUCCESS) { | 831 | if (hab_rvt_entry() != HAB_SUCCESS) { |
733 | puts("hab entry function fail\n"); | 832 | puts("hab entry function fail\n"); |
734 | goto hab_exit_failure_print_status; | 833 | goto hab_exit_failure_print_status; |
735 | } | 834 | } |
736 | 835 | ||
737 | status = hab_rvt_check_target(HAB_TGT_MEMORY, (void *)(ulong)ddr_start, bytes); | 836 | status = hab_rvt_check_target(HAB_TGT_MEMORY, (void *)(ulong)ddr_start, bytes); |
738 | if (status != HAB_SUCCESS) { | 837 | if (status != HAB_SUCCESS) { |
739 | printf("HAB check target 0x%08x-0x%08lx fail\n", | 838 | printf("HAB check target 0x%08x-0x%08lx fail\n", |
740 | ddr_start, ddr_start + bytes); | 839 | ddr_start, ddr_start + bytes); |
741 | goto hab_exit_failure_print_status; | 840 | goto hab_exit_failure_print_status; |
742 | } | 841 | } |
743 | #ifdef DEBUG | 842 | #ifdef DEBUG |
744 | printf("\nivt_offset = 0x%x, ivt addr = 0x%x\n", ivt_offset, ivt_addr); | 843 | printf("\nivt_offset = 0x%x, ivt addr = 0x%x\n", ivt_offset, ivt_addr); |
745 | printf("ivt entry = 0x%08x, dcd = 0x%08x, csf = 0x%08x\n", ivt->entry, | 844 | printf("ivt entry = 0x%08x, dcd = 0x%08x, csf = 0x%08x\n", ivt->entry, |
746 | ivt->dcd, ivt->csf); | 845 | ivt->dcd, ivt->csf); |
747 | puts("Dumping IVT\n"); | 846 | puts("Dumping IVT\n"); |
748 | print_buffer(ivt_addr, (void *)(ivt_addr), 4, 0x8, 0); | 847 | print_buffer(ivt_addr, (void *)(ivt_addr), 4, 0x8, 0); |
749 | 848 | ||
750 | puts("Dumping CSF Header\n"); | 849 | puts("Dumping CSF Header\n"); |
751 | print_buffer(ivt->csf, (void *)(ivt->csf), 4, 0x10, 0); | 850 | print_buffer(ivt->csf, (void *)(ivt->csf), 4, 0x10, 0); |
752 | 851 | ||
753 | #if !defined(CONFIG_SPL_BUILD) | 852 | #if !defined(CONFIG_SPL_BUILD) |
754 | get_hab_status(); | 853 | get_hab_status(); |
755 | #endif | 854 | #endif |
756 | 855 | ||
757 | puts("\nCalling authenticate_image in ROM\n"); | 856 | puts("\nCalling authenticate_image in ROM\n"); |
758 | printf("\tivt_offset = 0x%x\n", ivt_offset); | 857 | printf("\tivt_offset = 0x%x\n", ivt_offset); |
759 | printf("\tstart = 0x%08lx\n", start); | 858 | printf("\tstart = 0x%08lx\n", start); |
760 | printf("\tbytes = 0x%x\n", bytes); | 859 | printf("\tbytes = 0x%x\n", bytes); |
761 | #endif | 860 | #endif |
762 | 861 | ||
763 | #ifndef CONFIG_ARM64 | 862 | #ifndef CONFIG_ARM64 |
764 | /* | 863 | /* |
765 | * If the MMU is enabled, we have to notify the ROM | 864 | * If the MMU is enabled, we have to notify the ROM |
766 | * code, or it won't flush the caches when needed. | 865 | * code, or it won't flush the caches when needed. |
767 | * This is done, by setting the "pu_irom_mmu_enabled" | 866 | * This is done, by setting the "pu_irom_mmu_enabled" |
768 | * word to 1. You can find its address by looking in | 867 | * word to 1. You can find its address by looking in |
769 | * the ROM map. This is critical for | 868 | * the ROM map. This is critical for |
770 | * authenticate_image(). If MMU is enabled, without | 869 | * authenticate_image(). If MMU is enabled, without |
771 | * setting this bit, authentication will fail and may | 870 | * setting this bit, authentication will fail and may |
772 | * crash. | 871 | * crash. |
773 | */ | 872 | */ |
774 | /* Check MMU enabled */ | 873 | /* Check MMU enabled */ |
775 | if (is_soc_type(MXC_SOC_MX6) && get_cr() & CR_M) { | 874 | if (is_soc_type(MXC_SOC_MX6) && get_cr() & CR_M) { |
776 | if (is_mx6dq()) { | 875 | if (is_mx6dq()) { |
777 | /* | 876 | /* |
778 | * This won't work on Rev 1.0.0 of | 877 | * This won't work on Rev 1.0.0 of |
779 | * i.MX6Q/D, since their ROM doesn't | 878 | * i.MX6Q/D, since their ROM doesn't |
780 | * do cache flushes. don't think any | 879 | * do cache flushes. don't think any |
781 | * exist, so we ignore them. | 880 | * exist, so we ignore them. |
782 | */ | 881 | */ |
783 | if (!is_mx6dqp()) | 882 | if (!is_mx6dqp()) |
784 | writel(1, MX6DQ_PU_IROM_MMU_EN_VAR); | 883 | writel(1, MX6DQ_PU_IROM_MMU_EN_VAR); |
785 | } else if (is_mx6sdl()) { | 884 | } else if (is_mx6sdl()) { |
786 | writel(1, MX6DLS_PU_IROM_MMU_EN_VAR); | 885 | writel(1, MX6DLS_PU_IROM_MMU_EN_VAR); |
787 | } else if (is_mx6sl()) { | 886 | } else if (is_mx6sl()) { |
788 | writel(1, MX6SL_PU_IROM_MMU_EN_VAR); | 887 | writel(1, MX6SL_PU_IROM_MMU_EN_VAR); |
789 | } | 888 | } |
790 | } | 889 | } |
791 | #endif | 890 | #endif |
792 | 891 | ||
793 | load_addr = (ulong)hab_rvt_authenticate_image( | 892 | load_addr = (ulong)hab_rvt_authenticate_image( |
794 | HAB_CID_UBOOT, | 893 | HAB_CID_UBOOT, |
795 | ivt_offset, (void **)&start, | 894 | ivt_offset, (void **)&start, |
796 | (size_t *)&bytes, NULL); | 895 | (size_t *)&bytes, NULL); |
797 | if (hab_rvt_exit() != HAB_SUCCESS) { | 896 | if (hab_rvt_exit() != HAB_SUCCESS) { |
798 | puts("hab exit function fail\n"); | 897 | puts("hab exit function fail\n"); |
799 | load_addr = 0; | 898 | load_addr = 0; |
800 | } | 899 | } |
801 | 900 | ||
802 | hab_exit_failure_print_status: | 901 | hab_exit_failure_print_status: |
803 | #if !defined(CONFIG_SPL_BUILD) | 902 | #if !defined(CONFIG_SPL_BUILD) |
804 | get_hab_status(); | 903 | get_hab_status(); |
805 | #endif | 904 | #endif |
806 | 905 | ||
807 | hab_authentication_exit: | 906 | hab_authentication_exit: |
808 | 907 | ||
809 | if (load_addr != 0 || !imx_hab_is_enabled()) | 908 | if (load_addr != 0 || !imx_hab_is_enabled()) |
810 | result = 0; | 909 | result = 0; |
811 | 910 | ||
812 | return result; | 911 | return result; |
813 | } | 912 | } |
814 | 913 | ||
815 | int authenticate_image(uint32_t ddr_start, uint32_t raw_image_size) | 914 | int authenticate_image(uint32_t ddr_start, uint32_t raw_image_size) |
816 | { | 915 | { |
817 | uint32_t ivt_offset; | 916 | uint32_t ivt_offset; |
818 | size_t bytes; | 917 | size_t bytes; |
819 | 918 | ||
820 | ivt_offset = (raw_image_size + ALIGN_SIZE - 1) & | 919 | ivt_offset = (raw_image_size + ALIGN_SIZE - 1) & |
821 | ~(ALIGN_SIZE - 1); | 920 | ~(ALIGN_SIZE - 1); |
822 | bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE; | 921 | bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE; |
823 | 922 | ||
824 | return imx_hab_authenticate_image(ddr_start, bytes, ivt_offset); | 923 | return imx_hab_authenticate_image(ddr_start, bytes, ivt_offset); |
825 | } | 924 | } |
826 | 925 |
doc/imx/habv4/guides/mx6_mx7_secure_boot.txt
1 | +=======================================================+ | 1 | +=======================================================+ |
2 | + i.MX6, i.MX7 U-Boot Secure Boot guide using HABv4 + | 2 | + i.MX6, i.MX7 U-Boot Secure Boot guide using HABv4 + |
3 | +=======================================================+ | 3 | +=======================================================+ |
4 | 4 | ||
5 | 1. HABv4 secure boot process | 5 | 1. HABv4 secure boot process |
6 | ----------------------------- | 6 | ----------------------------- |
7 | 7 | ||
8 | This document describes a step-by-step procedure on how to sign and securely | 8 | This document describes a step-by-step procedure on how to sign and securely |
9 | boot an U-Boot image. It is assumed that the reader is familiar with basic | 9 | boot an U-Boot image. It is assumed that the reader is familiar with basic |
10 | HAB concepts and with the PKI tree generation. | 10 | HAB concepts and with the PKI tree generation. |
11 | 11 | ||
12 | Details about HAB can be found in the application note AN4581[1] and in the | 12 | Details about HAB can be found in the application note AN4581[1] and in the |
13 | introduction_habv4.txt document. | 13 | introduction_habv4.txt document. |
14 | 14 | ||
15 | 1.1 Building a u-boot-dtb.imx image supporting secure boot | 15 | 1.1 Building a u-boot-dtb.imx image supporting secure boot |
16 | ----------------------------------------------------------- | 16 | ----------------------------------------------------------- |
17 | 17 | ||
18 | The U-Boot provides support to secure boot configuration and also provide | 18 | The U-Boot provides support to secure boot configuration and also provide |
19 | access to the HAB APIs exposed by the ROM vector table, the support is | 19 | access to the HAB APIs exposed by the ROM vector table, the support is |
20 | enabled by selecting the CONFIG_SECURE_BOOT option. | 20 | enabled by selecting the CONFIG_SECURE_BOOT option. |
21 | 21 | ||
22 | When built with this configuration, the U-Boot provides extra functions for | 22 | When built with this configuration, the U-Boot provides extra functions for |
23 | HAB, such as the HAB status logs retrievement through the hab_status command | 23 | HAB, such as the HAB status logs retrievement through the hab_status command |
24 | and support for extending the root of trust. | 24 | and support for extending the root of trust. |
25 | 25 | ||
26 | The U-Boot also correctly pads the final image by aligning to the next 0xC00 | 26 | The U-Boot also correctly pads the final image by aligning to the next 0xC00 |
27 | address, so the CSF signature data generated by CST can be concatenated to | 27 | address, so the CSF signature data generated by CST can be concatenated to |
28 | image. | 28 | image. |
29 | 29 | ||
30 | The diagram below illustrate a signed u-boot-dtb.imx image layout: | 30 | The diagram below illustrate a signed u-boot-dtb.imx image layout: |
31 | 31 | ||
32 | ------- +-----------------------------+ <-- *start | 32 | ------- +-----------------------------+ <-- *start |
33 | ^ | Image Vector Table | | 33 | ^ | Image Vector Table | |
34 | | +-----------------------------+ <-- *boot_data | 34 | | +-----------------------------+ <-- *boot_data |
35 | | | Boot Data | | 35 | | | Boot Data | |
36 | | +-----------------------------+ <-- *dcd | 36 | | +-----------------------------+ <-- *dcd |
37 | | | DCD Table | | 37 | | | DCD Table | |
38 | | +-----------------------------+ | 38 | | +-----------------------------+ |
39 | Signed | | Padding | | 39 | Signed | | Padding | |
40 | Data | +-----------------------------+ <-- *entry | 40 | Data | +-----------------------------+ <-- *entry |
41 | | | | | 41 | | | | |
42 | | | | | 42 | | | | |
43 | | | u-boot-dtb.bin | | 43 | | | u-boot-dtb.bin | |
44 | | | | | 44 | | | | |
45 | | | | | 45 | | | | |
46 | | +-----------------------------+ | 46 | | +-----------------------------+ |
47 | v | Padding | | 47 | v | Padding | |
48 | ------- +-----------------------------+ <-- *csf | 48 | ------- +-----------------------------+ <-- *csf |
49 | | | | 49 | | | |
50 | | Command Sequence File (CSF) | | 50 | | Command Sequence File (CSF) | |
51 | | | | 51 | | | |
52 | +-----------------------------+ | 52 | +-----------------------------+ |
53 | | Padding (optional) | | 53 | | Padding (optional) | |
54 | +-----------------------------+ | 54 | +-----------------------------+ |
55 | 55 | ||
56 | 1.2 Enabling the secure boot support | 56 | 1.2 Enabling the secure boot support |
57 | ------------------------------------- | 57 | ------------------------------------- |
58 | 58 | ||
59 | The first step is to generate an U-Boot image supporting the HAB features | 59 | The first step is to generate an U-Boot image supporting the HAB features |
60 | mentioned above, this can be achieved by adding CONFIG_SECURE_BOOT to the | 60 | mentioned above, this can be achieved by adding CONFIG_SECURE_BOOT to the |
61 | build configuration: | 61 | build configuration: |
62 | 62 | ||
63 | - Defconfig: | 63 | - Defconfig: |
64 | 64 | ||
65 | CONFIG_SECURE_BOOT=y | 65 | CONFIG_SECURE_BOOT=y |
66 | 66 | ||
67 | - Kconfig: | 67 | - Kconfig: |
68 | 68 | ||
69 | ARM architecture -> Support i.MX HAB features | 69 | ARM architecture -> Support i.MX HAB features |
70 | 70 | ||
71 | 1.3 Creating the CSF description file | 71 | 1.3 Creating the CSF description file |
72 | -------------------------------------- | 72 | -------------------------------------- |
73 | 73 | ||
74 | The CSF contains all the commands that the ROM executes during the secure | 74 | The CSF contains all the commands that the ROM executes during the secure |
75 | boot. These commands instruct the HAB on which memory areas of the image | 75 | boot. These commands instruct the HAB on which memory areas of the image |
76 | to authenticate, which keys to install, use and etc. | 76 | to authenticate, which keys to install, use and etc. |
77 | 77 | ||
78 | CSF examples are available under doc/imx/habv4/csf_examples/ directory. | 78 | CSF examples are available under doc/imx/habv4/csf_examples/ directory. |
79 | 79 | ||
80 | A build log containing the "Authenticate Data" parameters is available after | 80 | A build log containing the "Authenticate Data" parameters is available after |
81 | the U-Boot build, the example below is a log for mx7dsabresd_defconfig target: | 81 | the U-Boot build, the example below is a log for mx7dsabresd_defconfig target: |
82 | 82 | ||
83 | - mkimage build log: | 83 | - mkimage build log: |
84 | 84 | ||
85 | $ cat u-boot-dtb.imx.log | 85 | $ cat u-boot-dtb.imx.log |
86 | 86 | ||
87 | Image Type: Freescale IMX Boot Image | 87 | Image Type: Freescale IMX Boot Image |
88 | Image Ver: 2 (i.MX53/6/7 compatible) | 88 | Image Ver: 2 (i.MX53/6/7 compatible) |
89 | Mode: DCD | 89 | Mode: DCD |
90 | Data Size: 667648 Bytes = 652.00 KiB = 0.64 MiB | 90 | Data Size: 667648 Bytes = 652.00 KiB = 0.64 MiB |
91 | Load Address: 877ff420 | 91 | Load Address: 877ff420 |
92 | Entry Point: 87800000 | 92 | Entry Point: 87800000 |
93 | HAB Blocks: 877ff400 00000000 0009ec00 | 93 | HAB Blocks: 877ff400 00000000 0009ec00 |
94 | ^^^^^^^^ ^^^^^^^^ ^^^^^^^^ | 94 | ^^^^^^^^ ^^^^^^^^ ^^^^^^^^ |
95 | | | | | 95 | | | | |
96 | | | ------- (1) | 96 | | | ------- (1) |
97 | | | | 97 | | | |
98 | | ---------------- (2) | 98 | | ---------------- (2) |
99 | | | 99 | | |
100 | ------------------------- (3) | 100 | ------------------------- (3) |
101 | 101 | ||
102 | (1) Size of area in file u-boot-dtb.imx to sign. | 102 | (1) Size of area in file u-boot-dtb.imx to sign. |
103 | This area should include the IVT, the Boot Data the DCD | 103 | This area should include the IVT, the Boot Data the DCD |
104 | and the U-Boot itself. | 104 | and the U-Boot itself. |
105 | (2) Start of area in u-boot-dtb.imx to sign. | 105 | (2) Start of area in u-boot-dtb.imx to sign. |
106 | (3) Start of area in RAM to authenticate. | 106 | (3) Start of area in RAM to authenticate. |
107 | 107 | ||
108 | - In "Authenticate Data" CSF command users can copy and past the output | 108 | - In "Authenticate Data" CSF command users can copy and past the output |
109 | addresses: | 109 | addresses: |
110 | 110 | ||
111 | Block = 0x877ff400 0x00000000 0x0009ec00 "u-boot-dtb.imx" | 111 | Block = 0x877ff400 0x00000000 0x0009ec00 "u-boot-dtb.imx" |
112 | 112 | ||
113 | 1.3.1 Avoiding Kernel crash when OP-TEE is enabled | 113 | 1.3.1 Avoiding Kernel crash when OP-TEE is enabled |
114 | --------------------------------------------------- | 114 | --------------------------------------------------- |
115 | 115 | ||
116 | For devices prior to HAB v4.4.0, the HAB code locks the Job Ring and DECO | 116 | For devices prior to HAB v4.4.0, the HAB code locks the Job Ring and DECO |
117 | master ID registers in HAB closed configuration. In case the user specific | 117 | master ID registers in HAB closed configuration. In case the user specific |
118 | application requires any changes in CAAM MID registers it's necessary to | 118 | application requires any changes in CAAM MID registers it's necessary to |
119 | add the "Unlock CAAM MID" command in CSF file. | 119 | add the "Unlock CAAM MID" command in CSF file. |
120 | 120 | ||
121 | The current NXP OP-TEE implementation expects the CAAM registers to be unlocked | 121 | The current NXP OP-TEE implementation expects the CAAM registers to be unlocked |
122 | when configuring CAAM to operate in non-secure TrustZone world. | 122 | when configuring CAAM to operate in non-secure TrustZone world. |
123 | 123 | ||
124 | - Add Unlock MID command in CSF: | 124 | - Add Unlock MID command in CSF: |
125 | 125 | ||
126 | [Unlock] | 126 | [Unlock] |
127 | Engine = CAAM | 127 | Engine = CAAM |
128 | Features = MID | 128 | Features = MID |
129 | 129 | ||
130 | 1.4 Signing the U-Boot binary | 130 | 1.4 Signing the U-Boot binary |
131 | ------------------------------ | 131 | ------------------------------ |
132 | 132 | ||
133 | The CST tool is used for singing the U-Boot binary and generating a CSF binary, | 133 | The CST tool is used for singing the U-Boot binary and generating a CSF binary, |
134 | users should input the CSF description file created in the step above and | 134 | users should input the CSF description file created in the step above and |
135 | should receive a CSF binary, which contains the CSF commands, SRK table, | 135 | should receive a CSF binary, which contains the CSF commands, SRK table, |
136 | signatures and certificates. | 136 | signatures and certificates. |
137 | 137 | ||
138 | - Create CSF binary file: | 138 | - Create CSF binary file: |
139 | 139 | ||
140 | $ ./cst -i csf_uboot.txt -o csf_uboot.bin | 140 | $ ./cst -i csf_uboot.txt -o csf_uboot.bin |
141 | 141 | ||
142 | - Append CSF signature to the end of U-Boot image: | 142 | - Append CSF signature to the end of U-Boot image: |
143 | 143 | ||
144 | $ cat u-boot-dtb.imx csf_uboot.bin > u-boot-signed.imx | 144 | $ cat u-boot-dtb.imx csf_uboot.bin > u-boot-signed.imx |
145 | 145 | ||
146 | The u-boot-signed.imx is the signed binary and should be flashed into the boot | 146 | The u-boot-signed.imx is the signed binary and should be flashed into the boot |
147 | media. | 147 | media. |
148 | 148 | ||
149 | - Flash signed U-Boot binary: | 149 | - Flash signed U-Boot binary: |
150 | 150 | ||
151 | $ sudo dd if=u-boot-signed.imx of=/dev/sd<x> bs=1K seek=1 && sync | 151 | $ sudo dd if=u-boot-signed.imx of=/dev/sd<x> bs=1K seek=1 && sync |
152 | 152 | ||
153 | 1.5 Programming SRK Hash | 153 | 1.5 Programming SRK Hash |
154 | ------------------------- | 154 | ------------------------- |
155 | 155 | ||
156 | As explained in AN4581[1] and in introduction_habv4.txt document the SRK Hash | 156 | As explained in AN4581[1] and in introduction_habv4.txt document the SRK Hash |
157 | fuse values are generated by the srktool and should be programmed in the | 157 | fuse values are generated by the srktool and should be programmed in the |
158 | SoC SRK_HASH[255:0] fuses. | 158 | SoC SRK_HASH[255:0] fuses. |
159 | 159 | ||
160 | Be careful when programming these values, as this data is the basis for the | 160 | Be careful when programming these values, as this data is the basis for the |
161 | root of trust. An error in SRK Hash results in a part that does not boot. | 161 | root of trust. An error in SRK Hash results in a part that does not boot. |
162 | 162 | ||
163 | The U-Boot fuse tool can be used for programming eFuses on i.MX SoCs. | 163 | The U-Boot fuse tool can be used for programming eFuses on i.MX SoCs. |
164 | 164 | ||
165 | - Dump SRK Hash fuses values in host machine: | 165 | - Dump SRK Hash fuses values in host machine: |
166 | 166 | ||
167 | $ hexdump -e '/4 "0x"' -e '/4 "%X""\n"' SRK_1_2_3_4_fuse.bin | 167 | $ hexdump -e '/4 "0x"' -e '/4 "%X""\n"' SRK_1_2_3_4_fuse.bin |
168 | 0x20593752 | 168 | 0x20593752 |
169 | 0x6ACE6962 | 169 | 0x6ACE6962 |
170 | 0x26E0D06C | 170 | 0x26E0D06C |
171 | 0xFC600661 | 171 | 0xFC600661 |
172 | 0x1240E88F | 172 | 0x1240E88F |
173 | 0x1209F144 | 173 | 0x1209F144 |
174 | 0x831C8117 | 174 | 0x831C8117 |
175 | 0x1190FD4D | 175 | 0x1190FD4D |
176 | 176 | ||
177 | - Program SRK_HASH[255:0] fuses, using i.MX6 series as example: | 177 | - Program SRK_HASH[255:0] fuses, using i.MX6 series as example: |
178 | 178 | ||
179 | => fuse prog 3 0 0x20593752 | 179 | => fuse prog 3 0 0x20593752 |
180 | => fuse prog 3 1 0x6ACE6962 | 180 | => fuse prog 3 1 0x6ACE6962 |
181 | => fuse prog 3 2 0x26E0D06C | 181 | => fuse prog 3 2 0x26E0D06C |
182 | => fuse prog 3 3 0xFC600661 | 182 | => fuse prog 3 3 0xFC600661 |
183 | => fuse prog 3 4 0x1240E88F | 183 | => fuse prog 3 4 0x1240E88F |
184 | => fuse prog 3 5 0x1209F144 | 184 | => fuse prog 3 5 0x1209F144 |
185 | => fuse prog 3 6 0x831C8117 | 185 | => fuse prog 3 6 0x831C8117 |
186 | => fuse prog 3 7 0x1190FD4D | 186 | => fuse prog 3 7 0x1190FD4D |
187 | 187 | ||
188 | The table below lists the SRK_HASH bank and word according to the i.MX device: | 188 | The table below lists the SRK_HASH bank and word according to the i.MX device: |
189 | 189 | ||
190 | +-------------------+---------------+---------------+---------------+ | 190 | +-------------------+---------------+---------------+---------------+ |
191 | | | i.MX6 Series | i.MX7D/S | i.MX7ULP | | 191 | | | i.MX6 Series | i.MX7D/S | i.MX7ULP | |
192 | +-------------------+---------------+---------------+---------------+ | 192 | +-------------------+---------------+---------------+---------------+ |
193 | | SRK_HASH[31:00] | bank 3 word 0 | bank 6 word 0 | bank 5 word 0 | | 193 | | SRK_HASH[31:00] | bank 3 word 0 | bank 6 word 0 | bank 5 word 0 | |
194 | +-------------------+---------------+---------------+---------------+ | 194 | +-------------------+---------------+---------------+---------------+ |
195 | | SRK_HASH[63:32] | bank 3 word 1 | bank 6 word 1 | bank 5 word 1 | | 195 | | SRK_HASH[63:32] | bank 3 word 1 | bank 6 word 1 | bank 5 word 1 | |
196 | +-------------------+---------------+---------------+---------------+ | 196 | +-------------------+---------------+---------------+---------------+ |
197 | | SRK_HASH[95:64] | bank 3 word 2 | bank 6 word 2 | bank 5 word 2 | | 197 | | SRK_HASH[95:64] | bank 3 word 2 | bank 6 word 2 | bank 5 word 2 | |
198 | +-------------------+---------------+---------------+---------------+ | 198 | +-------------------+---------------+---------------+---------------+ |
199 | | SRK_HASH[127:96] | bank 3 word 3 | bank 6 word 3 | bank 5 word 3 | | 199 | | SRK_HASH[127:96] | bank 3 word 3 | bank 6 word 3 | bank 5 word 3 | |
200 | +-------------------+---------------+---------------+---------------+ | 200 | +-------------------+---------------+---------------+---------------+ |
201 | | SRK_HASH[159:128] | bank 3 word 4 | bank 7 word 0 | bank 5 word 4 | | 201 | | SRK_HASH[159:128] | bank 3 word 4 | bank 7 word 0 | bank 5 word 4 | |
202 | +-------------------+---------------+---------------+---------------+ | 202 | +-------------------+---------------+---------------+---------------+ |
203 | | SRK_HASH[191:160] | bank 3 word 5 | bank 7 word 1 | bank 5 word 5 | | 203 | | SRK_HASH[191:160] | bank 3 word 5 | bank 7 word 1 | bank 5 word 5 | |
204 | +-------------------+---------------+---------------+---------------+ | 204 | +-------------------+---------------+---------------+---------------+ |
205 | | SRK_HASH[223:192] | bank 3 word 6 | bank 7 word 2 | bank 5 word 6 | | 205 | | SRK_HASH[223:192] | bank 3 word 6 | bank 7 word 2 | bank 5 word 6 | |
206 | +-------------------+---------------+---------------+---------------+ | 206 | +-------------------+---------------+---------------+---------------+ |
207 | | SRK_HASH[255:224] | bank 3 word 7 | bank 7 word 3 | bank 5 word 7 | | 207 | | SRK_HASH[255:224] | bank 3 word 7 | bank 7 word 3 | bank 5 word 7 | |
208 | +-------------------+---------------+---------------+---------------+ | 208 | +-------------------+---------------+---------------+---------------+ |
209 | 209 | ||
210 | 1.6 Verifying HAB events | 210 | 1.6 Verifying HAB events |
211 | ------------------------- | 211 | ------------------------- |
212 | 212 | ||
213 | The next step is to verify that the signature attached to U-Boot is | 213 | The next step is to verify that the signature attached to U-Boot is |
214 | successfully processed without errors. HAB generates events when processing | 214 | successfully processed without errors. HAB generates events when processing |
215 | the commands if it encounters issues. | 215 | the commands if it encounters issues. |
216 | 216 | ||
217 | The hab_status U-Boot command call the hab_report_event() and hab_status() | 217 | The hab_status U-Boot command call the hab_report_event() and hab_status() |
218 | HAB API functions to verify the processor security configuration and status. | 218 | HAB API functions to verify the processor security configuration and status. |
219 | This command displays any events that were generated during the process. | 219 | This command displays any events that were generated during the process. |
220 | 220 | ||
221 | Prior to closing the device users should ensure no HAB events were found, as | 221 | Prior to closing the device users should ensure no HAB events were found, as |
222 | the example below: | 222 | the example below: |
223 | 223 | ||
224 | - Verify HAB events: | 224 | - Verify HAB events: |
225 | 225 | ||
226 | => hab_status | 226 | => hab_status |
227 | 227 | ||
228 | Secure boot disabled | 228 | Secure boot disabled |
229 | 229 | ||
230 | HAB Configuration: 0xf0, HAB State: 0x66 | 230 | HAB Configuration: 0xf0, HAB State: 0x66 |
231 | No HAB Events Found! | 231 | No HAB Events Found! |
232 | 232 | ||
233 | 1.6.1 Verifying HAB events in i.MX7ULP | ||
234 | --------------------------------------- | ||
235 | |||
236 | When booting i.MX7ULP in low power or dual boot modes the M4 binary is | ||
237 | authenticated by an independent HAB in M4 ROM code using a | ||
238 | different SRK key set. | ||
239 | |||
240 | The U-Boot provides a M4 option in hab_status command so users can retrieve | ||
241 | M4 HAB failure and warning events. | ||
242 | |||
243 | - Verify HAB M4 events: | ||
244 | |||
245 | => hab_status m4 | ||
246 | |||
247 | Secure boot disabled | ||
248 | |||
249 | HAB Configuration: 0xf0, HAB State: 0x66 | ||
250 | No HAB Events Found! | ||
251 | |||
252 | As HAB M4 API cannot be called from A7 core the command is parsing the M4 HAB | ||
253 | persistent memory region, M4 software should not modify this reserved region. | ||
254 | |||
255 | Details about HAB persistent memory region can be found in AN12263[2]. | ||
256 | |||
233 | 1.7 Closing the device | 257 | 1.7 Closing the device |
234 | ----------------------- | 258 | ----------------------- |
235 | 259 | ||
236 | After the device successfully boots a signed image without generating any HAB | 260 | After the device successfully boots a signed image without generating any HAB |
237 | events, it is safe to close the device. This is the last step in the HAB | 261 | events, it is safe to close the device. This is the last step in the HAB |
238 | process, and is achieved by programming the SEC_CONFIG[1] fuse bit. | 262 | process, and is achieved by programming the SEC_CONFIG[1] fuse bit. |
239 | 263 | ||
240 | Once the fuse is programmed, the chip does not load an image that has not been | 264 | Once the fuse is programmed, the chip does not load an image that has not been |
241 | signed using the correct PKI tree. | 265 | signed using the correct PKI tree. |
242 | 266 | ||
243 | - Program SEC_CONFIG[1] fuse, using i.MX6 series as example: | 267 | - Program SEC_CONFIG[1] fuse, using i.MX6 series as example: |
244 | 268 | ||
245 | => fuse prog 0 6 0x00000002 | 269 | => fuse prog 0 6 0x00000002 |
246 | 270 | ||
247 | The table below list the SEC_CONFIG[1] bank and word according to the i.MX | 271 | The table below list the SEC_CONFIG[1] bank and word according to the i.MX |
248 | device: | 272 | device: |
249 | 273 | ||
250 | +--------------+-----------------+------------+ | 274 | +--------------+-----------------+------------+ |
251 | | Device | Bank and Word | Value | | 275 | | Device | Bank and Word | Value | |
252 | +--------------+-----------------+------------+ | 276 | +--------------+-----------------+------------+ |
253 | | i.MX6 Series | bank 0 word 6 | 0x00000002 | | 277 | | i.MX6 Series | bank 0 word 6 | 0x00000002 | |
254 | +--------------+-----------------+------------+ | 278 | +--------------+-----------------+------------+ |
255 | | i.MX7D/S | bank 1 word 3 | 0x02000000 | | 279 | | i.MX7D/S | bank 1 word 3 | 0x02000000 | |
256 | +--------------+-----------------+------------+ | 280 | +--------------+-----------------+------------+ |
257 | | i.MX7ULP | bank 29 word 6 | 0x80000000 | | 281 | | i.MX7ULP | bank 29 word 6 | 0x80000000 | |
258 | +--------------+-----------------+------------+ | 282 | +--------------+-----------------+------------+ |
259 | 283 | ||
260 | 1.8 Completely secure the device | 284 | 1.8 Completely secure the device |
261 | --------------------------------- | 285 | --------------------------------- |
262 | 286 | ||
263 | Additional fuses can be programmed for completely secure the device, more | 287 | Additional fuses can be programmed for completely secure the device, more |
264 | details about these fuses and their possible impact can be found at AN4581[1]. | 288 | details about these fuses and their possible impact can be found at AN4581[1]. |
265 | 289 | ||
266 | - Program SRK_LOCK, using i.MX6 series as example: | 290 | - Program SRK_LOCK, using i.MX6 series as example: |
267 | 291 | ||
268 | => fuse prog 0 0 0x4000 | 292 | => fuse prog 0 0 0x4000 |
269 | 293 | ||
270 | - Program DIR_BT_DIS, using i.MX6 series as example: | 294 | - Program DIR_BT_DIS, using i.MX6 series as example: |
271 | 295 | ||
272 | => fuse prog 0 6 0x8 | 296 | => fuse prog 0 6 0x8 |
273 | 297 | ||
274 | - Program SJC_DISABLE, using i.MX6 series as example: | 298 | - Program SJC_DISABLE, using i.MX6 series as example: |
275 | 299 | ||
276 | => fuse prog 0 6 0x100000 | 300 | => fuse prog 0 6 0x100000 |
277 | 301 | ||
278 | - JTAG_SMODE, using i.MX6 series as example: | 302 | - JTAG_SMODE, using i.MX6 series as example: |
279 | 303 | ||
280 | => fuse prog 0 6 0xC00000 | 304 | => fuse prog 0 6 0xC00000 |
281 | 305 | ||
282 | The table below list the SRK_LOCK, DIR_BT_DIS, SJC_DISABLE, and JTAG_SMODE bank | 306 | The table below list the SRK_LOCK, DIR_BT_DIS, SJC_DISABLE, and JTAG_SMODE bank |
283 | and word according to the i.MX device: | 307 | and word according to the i.MX device: |
284 | 308 | ||
285 | +--------------+---------------+------------+ | 309 | +--------------+---------------+------------+ |
286 | | Device | Bank and Word | Value | | 310 | | Device | Bank and Word | Value | |
287 | +--------------+---------------+------------+ | 311 | +--------------+---------------+------------+ |
288 | | SRK_LOCK | | 312 | | SRK_LOCK | |
289 | +-------------------------------------------+ | 313 | +-------------------------------------------+ |
290 | | i.MX6 Series | bank 0 word 0 | 0x00004000 | | 314 | | i.MX6 Series | bank 0 word 0 | 0x00004000 | |
291 | +--------------+---------------+------------+ | 315 | +--------------+---------------+------------+ |
292 | | i.MX7D/S | bank 0 word 0 | 0x00000200 | | 316 | | i.MX7D/S | bank 0 word 0 | 0x00000200 | |
293 | +--------------+---------------+------------+ | 317 | +--------------+---------------+------------+ |
294 | | i.MX7ULP | bank 1 word 1 | 0x00000080 | | 318 | | i.MX7ULP | bank 1 word 1 | 0x00000080 | |
295 | +--------------+---------------+------------+ | 319 | +--------------+---------------+------------+ |
296 | | DIR_BT_DIS | | 320 | | DIR_BT_DIS | |
297 | +-------------------------------------------+ | 321 | +-------------------------------------------+ |
298 | | i.MX6 Series | bank 0 word 6 | 0x00000008 | | 322 | | i.MX6 Series | bank 0 word 6 | 0x00000008 | |
299 | +--------------+---------------+------------+ | 323 | +--------------+---------------+------------+ |
300 | | i.MX7D/S | bank 1 word 3 | 0x08000000 | | 324 | | i.MX7D/S | bank 1 word 3 | 0x08000000 | |
301 | +--------------+---------------+------------+ | 325 | +--------------+---------------+------------+ |
302 | | i.MX7ULP | bank 1 word 1 | 0x00002000 | | 326 | | i.MX7ULP | bank 1 word 1 | 0x00002000 | |
303 | +--------------+---------------+------------+ | 327 | +--------------+---------------+------------+ |
304 | | SJC_DISABLE | | 328 | | SJC_DISABLE | |
305 | +-------------------------------------------+ | 329 | +-------------------------------------------+ |
306 | | i.MX6 Series | bank 0 word 6 | 0x00100000 | | 330 | | i.MX6 Series | bank 0 word 6 | 0x00100000 | |
307 | +--------------+---------------+------------+ | 331 | +--------------+---------------+------------+ |
308 | | i.MX7D/S | bank 1 word 3 | 0x00200000 | | 332 | | i.MX7D/S | bank 1 word 3 | 0x00200000 | |
309 | +--------------+---------------+------------+ | 333 | +--------------+---------------+------------+ |
310 | | i.MX7ULP | bank 1 word 1 | 0x00000020 | | 334 | | i.MX7ULP | bank 1 word 1 | 0x00000020 | |
311 | +--------------+---------------+------------+ | 335 | +--------------+---------------+------------+ |
312 | | JTAG_SMODE | | 336 | | JTAG_SMODE | |
313 | +-------------------------------------------+ | 337 | +-------------------------------------------+ |
314 | | i.MX6 Series | bank 0 word 6 | 0x00C00000 | | 338 | | i.MX6 Series | bank 0 word 6 | 0x00C00000 | |
315 | +--------------+---------------+------------+ | 339 | +--------------+---------------+------------+ |
316 | | i.MX7D/S | bank 1 word 3 | 0x00C00000 | | 340 | | i.MX7D/S | bank 1 word 3 | 0x00C00000 | |
317 | +--------------+---------------+------------+ | 341 | +--------------+---------------+------------+ |
318 | | i.MX7ULP | bank 1 word 1 | 0x000000C0 | | 342 | | i.MX7ULP | bank 1 word 1 | 0x000000C0 | |
319 | +--------------+---------------+------------+ | 343 | +--------------+---------------+------------+ |
320 | 344 | ||
321 | 2. Extending the root of trust | 345 | 2. Extending the root of trust |
322 | ------------------------------- | 346 | ------------------------------- |
323 | 347 | ||
324 | The High Assurance Boot (HAB) code located in the on-chip ROM provides an | 348 | The High Assurance Boot (HAB) code located in the on-chip ROM provides an |
325 | Application Programming Interface (API) making it possible to call back | 349 | Application Programming Interface (API) making it possible to call back |
326 | into the HAB code for authenticating additional boot images. | 350 | into the HAB code for authenticating additional boot images. |
327 | 351 | ||
328 | The U-Boot supports this feature and can be used to authenticate the Linux | 352 | The U-Boot supports this feature and can be used to authenticate the Linux |
329 | Kernel Image. | 353 | Kernel Image. |
330 | 354 | ||
331 | The process of signing an additional image is similar to the U-Boot. | 355 | The process of signing an additional image is similar to the U-Boot. |
332 | The diagram below illustrate the zImage layout: | 356 | The diagram below illustrate the zImage layout: |
333 | 357 | ||
334 | ------- +-----------------------------+ <-- *load_address | 358 | ------- +-----------------------------+ <-- *load_address |
335 | ^ | | | 359 | ^ | | |
336 | | | | | 360 | | | | |
337 | | | | | 361 | | | | |
338 | | | | | 362 | | | | |
339 | | | zImage | | 363 | | | zImage | |
340 | Signed | | | | 364 | Signed | | | |
341 | Data | | | | 365 | Data | | | |
342 | | | | | 366 | | | | |
343 | | +-----------------------------+ | 367 | | +-----------------------------+ |
344 | | | Padding Next Boundary | | 368 | | | Padding Next Boundary | |
345 | | +-----------------------------+ <-- *ivt | 369 | | +-----------------------------+ <-- *ivt |
346 | v | Image Vector Table | | 370 | v | Image Vector Table | |
347 | ------- +-----------------------------+ <-- *csf | 371 | ------- +-----------------------------+ <-- *csf |
348 | | | | 372 | | | |
349 | | Command Sequence File (CSF) | | 373 | | Command Sequence File (CSF) | |
350 | | | | 374 | | | |
351 | +-----------------------------+ | 375 | +-----------------------------+ |
352 | | Padding (optional) | | 376 | | Padding (optional) | |
353 | +-----------------------------+ | 377 | +-----------------------------+ |
354 | 378 | ||
355 | 2.1 Padding the image | 379 | 2.1 Padding the image |
356 | ---------------------- | 380 | ---------------------- |
357 | 381 | ||
358 | The zImage must be padded to the next boundary address (0x1000), for instance | 382 | The zImage must be padded to the next boundary address (0x1000), for instance |
359 | if the image size is 0x649920 it must be padded to 0x64A000. | 383 | if the image size is 0x649920 it must be padded to 0x64A000. |
360 | 384 | ||
361 | The tool objcopy can be used for padding the image. | 385 | The tool objcopy can be used for padding the image. |
362 | 386 | ||
363 | - Pad the zImage: | 387 | - Pad the zImage: |
364 | 388 | ||
365 | $ objcopy -I binary -O binary --pad-to 0x6EA000 --gap-fill=0x00 \ | 389 | $ objcopy -I binary -O binary --pad-to 0x6EA000 --gap-fill=0x00 \ |
366 | zImage zImage_pad.bin | 390 | zImage zImage_pad.bin |
367 | 391 | ||
368 | 2.2 Generating Image Vector Table | 392 | 2.2 Generating Image Vector Table |
369 | ---------------------------------- | 393 | ---------------------------------- |
370 | 394 | ||
371 | The HAB code requires an Image Vector Table (IVT) for determining the image | 395 | The HAB code requires an Image Vector Table (IVT) for determining the image |
372 | length and the CSF location. Since zImage does not include an IVT this has | 396 | length and the CSF location. Since zImage does not include an IVT this has |
373 | to be manually created and appended to the end of the padded zImage, the | 397 | to be manually created and appended to the end of the padded zImage, the |
374 | script genIVT.pl in script_examples directory can be used as reference. | 398 | script genIVT.pl in script_examples directory can be used as reference. |
375 | 399 | ||
376 | - Generate IVT: | 400 | - Generate IVT: |
377 | 401 | ||
378 | $ genIVT.pl | 402 | $ genIVT.pl |
379 | 403 | ||
380 | Note: The load Address may change depending on the device. | 404 | Note: The load Address may change depending on the device. |
381 | 405 | ||
382 | - Append the ivt.bin at the end of the padded zImage: | 406 | - Append the ivt.bin at the end of the padded zImage: |
383 | 407 | ||
384 | $ cat zImage_pad.bin ivt.bin > zImage_pad_ivt.bin | 408 | $ cat zImage_pad.bin ivt.bin > zImage_pad_ivt.bin |
385 | 409 | ||
386 | 2.3 Signing the image | 410 | 2.3 Signing the image |
387 | ---------------------- | 411 | ---------------------- |
388 | 412 | ||
389 | A CSF file has to be created to sign the image. HAB does not allow to change | 413 | A CSF file has to be created to sign the image. HAB does not allow to change |
390 | the SRK once the first image is authenticated, so the same SRK key used in | 414 | the SRK once the first image is authenticated, so the same SRK key used in |
391 | U-Boot must be used when extending the root of trust. | 415 | U-Boot must be used when extending the root of trust. |
392 | 416 | ||
393 | CSF examples are available in ../csf_examples/additional_images/ | 417 | CSF examples are available in ../csf_examples/additional_images/ |
394 | directory. | 418 | directory. |
395 | 419 | ||
396 | - Create CSF binary file: | 420 | - Create CSF binary file: |
397 | 421 | ||
398 | $ ./cst --i csf_additional_images.txt --o csf_zImage.bin | 422 | $ ./cst --i csf_additional_images.txt --o csf_zImage.bin |
399 | 423 | ||
400 | - Attach the CSF binary to the end of the image: | 424 | - Attach the CSF binary to the end of the image: |
401 | 425 | ||
402 | $ cat zImage_pad_ivt.bin csf_zImage.bin > zImage_signed.bin | 426 | $ cat zImage_pad_ivt.bin csf_zImage.bin > zImage_signed.bin |
403 | 427 | ||
404 | 2.4 Verifying HAB events | 428 | 2.4 Verifying HAB events |
405 | ------------------------- | 429 | ------------------------- |
406 | 430 | ||
407 | The U-Boot includes the hab_auth_img command which can be used for | 431 | The U-Boot includes the hab_auth_img command which can be used for |
408 | authenticating and troubleshooting the signed image, zImage must be | 432 | authenticating and troubleshooting the signed image, zImage must be |
409 | loaded at the load address specified in the IVT. | 433 | loaded at the load address specified in the IVT. |
410 | 434 | ||
411 | - Authenticate additional image: | 435 | - Authenticate additional image: |
412 | 436 | ||
413 | => hab_auth_img <Load Address> <Image Size> <IVT Offset> | 437 | => hab_auth_img <Load Address> <Image Size> <IVT Offset> |
414 | 438 | ||
415 | If no HAB events were found the zImage is successfully signed. | 439 | If no HAB events were found the zImage is successfully signed. |
416 | 440 | ||
417 | References: | 441 | References: |
418 | [1] AN4581: "Secure Boot on i.MX 50, i.MX 53, i.MX 6 and i.MX 7 Series using | 442 | [1] AN4581: "Secure Boot on i.MX 50, i.MX 53, i.MX 6 and i.MX 7 Series using |
419 | HABv4" - Rev 2. | 443 | HABv4" - Rev 2. |
444 | [2] AN12263: "HABv4 RVT Guidelines and Recommendations" - Rev 0. | ||
420 | 445 |