Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: arch/arm/cpu/arm_cortexa9/tegra2/warmboot.c

Issue 4841001: Tegra2: implement Warmboot code and lp0_vec (Closed) Base URL: http://git.chromium.org/git/u-boot-next.git@chromeos-v2010.09
Patch Set: Add GPL headers & fix some 80-column issues Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * (C) Copyright 2010
3 * NVIDIA Corporation <www.nvidia.com>
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24 #include <common.h>
25 #include <asm/arch/nv_drf.h>
26 #include <asm/arch/nvboot_error.h>
27 #include <asm/arch/nvcommon.h>
28 #include <asm/arch/nverror.h>
29 #include <asm/arch/tegra2.h>
30 #include <asm/arch/nv_hardware_access.h>
31 #include <asm/arch/warmboot.h>
32
33 NvBootError sign_data_block(NvU8 *source,
34 NvU32 length,
35 NvU8 *hash);
36
37 /* -------------------------------------
38 * Configuration parameters
39 * -------------------------------------
40 */
41
42 /* -------------------------------------
43 * Definitions
44 * -------------------------------------
45 */
46
47 /* NOTE: If more than one of the following is enabled, only one of them will
48 * actually be used. RANDOM takes precedence over PATTERN and ZERO, and
49 * PATTERN takes precedence overy ZERO.
50 */
51 #define RANDOM_AES_BLOCK_IS_RANDOM 1 /* to randomize the header */
52 #define RANDOM_AES_BLOCK_IS_PATTERN 1 /* to patternize the header */
53 #define RANDOM_AES_BLOCK_IS_ZERO 1 /* to clear the header */
54
55 /* Address at which AP20 WB0 code runs */
56 /* The address must not overlap the bootrom's IRAM usage */
57 #define AP20_WB0_RUN_ADDRESS 0x40020000
58 #define AP20_IRAM_BASE 0x40000000
59
60 /* -------------------------------------
61 * Global External Labels
62 * -------------------------------------
63 */
64
65 void wb_start(void); /* Start of WB assembly code */
66 void wb_end(void); /* End of WB assembly code */
67
68 #define NV_ADDRESS_MAP_FUSE_BASE 0x7000F800UL
69 #define FUSE_PRODUCTION_MODE_0 _MK_ADDR_CONST(0x100)
70 #define FUSE_FA_0 _MK_ADDR_CONST(0x148)
71 #define FUSE_SECURITY_MODE_0 _MK_ADDR_CONST(0x1a0)
72
73 /* -------------------------------------
74 * Local Functions
75 * -------------------------------------
76 */
77 static NvU32 get_major_version(void)
78 {
79 NvU32 reg = 0;
80 NvU32 major_id = 0;
81
82 reg = NV_READ32( NV_ADDRESS_MAP_APB_MISC_BASE + APB_MISC_GP_HIDREV_0) ;
83 major_id = NV_DRF_VAL(APB_MISC, GP_HIDREV, MAJORREV, reg);
84 return major_id;
85 }
86
87 static NvBool is_production_mode_fuse_set(void)
88 {
89 NvU32 reg;
90
91 reg = NV_READ32(NV_ADDRESS_MAP_FUSE_BASE + FUSE_PRODUCTION_MODE_0);
92 if (reg)
93 return NV_TRUE;
94 else
95 return NV_FALSE;
96 }
97
98 static NvBool is_odm_production_mode_fuse_set(void)
99 {
100 NvU32 reg;
101
102 reg = NV_READ32(NV_ADDRESS_MAP_FUSE_BASE + FUSE_SECURITY_MODE_0);
103 if (reg)
104 return NV_TRUE;
105 else
106 return NV_FALSE;
107 }
108
109 static NvBool ap20_is_failure_analysis_mode(void)
110 {
111 volatile NvU32 reg;
112
113 reg = NV_READ32(NV_ADDRESS_MAP_FUSE_BASE + FUSE_FA_0);
114 if (reg)
115 return NV_TRUE;
116 else
117 return NV_FALSE;
118 }
119
120 static NvBool ap20_is_odm_production_mode(void)
121 {
122 if (!ap20_is_failure_analysis_mode() &&
123 is_odm_production_mode_fuse_set())
124 return NV_TRUE;
125 else
126 return NV_FALSE;
127 }
128
129 static NvBool ap20_is_production_mode(void)
130 {
131 if (get_major_version() == 0)
132 return NV_TRUE;
133
134 if (!ap20_is_failure_analysis_mode() &&
135 is_production_mode_fuse_set() &&
136 !is_odm_production_mode_fuse_set())
137 return NV_TRUE;
138 else
139 return NV_FALSE;
140 }
141
142 static NvBool fuse_get_ap20_hal(nv_fuse_hal *hal)
143 {
144 NvU32 reg;
145
146 reg = NV_READ32(NV_ADDRESS_MAP_APB_MISC_BASE + APB_MISC_GP_HIDREV_0);
147 if (NV_DRF_VAL(APB_MISC_GP, HIDREV, CHIPID, reg) == 0x20) {
148 hal->is_odm_production_mode = ap20_is_odm_production_mode;
149 hal->is_nv_production_mode = ap20_is_production_mode;
150 return NV_TRUE;
151 }
152 return NV_FALSE;
153 }
154
155 static nvbl_operating_mode nv_fuse_get_operation_mode(void)
156 {
157 nv_fuse_hal hal;
158 if (fuse_get_ap20_hal(&hal)) {
159 if (hal.is_odm_production_mode()) {
160 printf("!!! OdmProductionMode is not supported !!!\n");
161 return nvbl_mode_undefined;
162 } else {
163 if (hal.is_nv_production_mode())
164 return nvbl_mode_production;
165 else
166 return nvbl_mode_undefined;
167 }
168 }
169 return nvbl_mode_undefined;
170 }
171
172 static NvU64 query_random_seed(void)
173 {
174 return 0;
175 }
176
177 static void determine_crypto_options(NvBool* is_encrypted, NvBool* is_signed,
178 NvBool* use_zero_key)
179 {
180 switch (nv_fuse_get_operation_mode()) {
181 case nvbl_mode_production:
182 *is_encrypted = NV_FALSE;
183 *is_signed = NV_TRUE;
184 *use_zero_key = NV_TRUE;
185 break;
186
187 case nvbl_mode_undefined:
188 default:
189 *is_encrypted = NV_FALSE;
190 *is_signed = NV_FALSE;
191 *use_zero_key = NV_FALSE;
192 break;
193 }
194 }
195
196 static NvBootError sign_wb_code(NvU32 start, NvU32 length, NvBool use_zero_key)
197 {
198 NvBootError e;
199 NvU8 *source; /* Pointer to source */
200 NvU8 *hash;
201
202 /* Calculate AES block parameters. */
203 source = (NvU8 *)(start + offsetof(nvboot_wb_header, random_aes_block));
204 length -= offsetof(nvboot_wb_header, random_aes_block);
205 hash = (NvU8 *)(start + offsetof(nvboot_wb_header, hash));
206 e = sign_data_block(source, length, hash);
207 return e;
208 }
209
210 /* -------------------------------------
211 * Global Functions
212 * -------------------------------------
213 */
214
215 NvBootError prepare_wb_code(NvU32 seg_address, NvU32 seg_length)
216 {
217 NvBootError e = NvBootError_NotInitialized; /* Error code */
218
219 NvU32 start; /* start of the actual code */
220 NvU32 end; /* end of the actual code */
221 NvU32 actual_length; /* length of the actual code */
222 NvU32 length; /* length of the
223 signed/encrypted code */
224 nvboot_wb_header *src_header; /* Pointer to src WB header */
225 nvboot_wb_header *dst_header; /* Pointer to dest WB header */
226 NvBool is_encrypted; /* Segment is encrypted */
227 NvBool is_signed; /* Segment is signed */
228 NvBool use_zero_key; /* Use key of all zeros */
229
230 /* Determine crypto options. */
231 determine_crypto_options(&is_encrypted, &is_signed, &use_zero_key);
232
233 /* Get the actual code limits. */
234 start = (NvU32)wb_start;
235 end = (NvU32)wb_end;
236 actual_length = end - start;
237 length = ((actual_length + 15) >> 4) << 4;
238
239 /* The region specified by seg_address must be in SDRAM and must be
240 * nonzero in length.
241 */
242 if ((seg_length == 0) ||(seg_address == 0) ||
243 (seg_address >= AP20_IRAM_BASE)) {
244 goto fail;
245 }
246
247 /* Things must be 16-byte aligned. */
248 if ((seg_length & 0xF) || (seg_address & 0xF)) {
249 goto fail;
250 }
251
252 /* Will the code fit? */
253 if (seg_length < length) {
254 goto fail;
255 }
256
257 /* Get a pointers to the source and destination region header. */
258 src_header = (nvboot_wb_header*)start;
259 dst_header = (nvboot_wb_header*)seg_address;
260
261 /* Populate the random_aes_block as requested. */
262 #if RANDOM_AES_BLOCK_IS_RANDOM
263 {
264 NvU64 *pAesBlock = (NvU64*)&(src_header->random_aes_block);
265 NvU64 *pEnd = (NvU64*)(((NvU32)pAesBlock) +
266 sizeof(src_header->random_aes_block));
267 do {
268 *pAesBlock++ = query_random_seed();
269 } while (pAesBlock < pEnd);
270 }
271 #elif RANDOM_AES_BLOCK_IS_PATTERN
272 {
273 NvU32 *pAesBlock = (NvU32*)&(src_header->random_aes_block);
274 NvU32 *pEnd = (NvU32*)(((NvU32)pAesBlock) +
275 sizeof(src_header->random_aes_block));
276
277 do {
278 *pAesBlock++ = RANDOM_AES_BLOCK_IS_PATTERN;
279 } while (pAesBlock < pEnd);
280 }
281 #elif RANDOM_AES_BLOCK_IS_ZERO
282 {
283 NvU32 *pAesBlock = (NvU32*)&(src_header->random_aes_block);
284 NvU32 *pEnd = (NvU32*)(((NvU32)pAesBlock) +
285 sizeof(src_header->random_aes_block));
286
287 do {
288 *pAesBlock++ = 0;
289 } while (pRandomAesBlock < pEnd);
290 }
291 #endif
292
293 /* Populate the header. */
294 src_header->length_in_secure = length;
295 src_header->length_secure = length;
296 src_header->destination = AP20_WB0_RUN_ADDRESS;
297 src_header->entry_point = AP20_WB0_RUN_ADDRESS;
298 src_header->code_length = length - sizeof(nvboot_wb_header);
299
300 if (is_encrypted) {
301 /* Encryption is not supported */
302 printf("!!!! No Encrypion implemented!!!!\n");
303 dst_header->length_in_secure = 0;
304 e = NvBootError_Unimplemented;
305 goto fail;
306 } else {
307 /* No, just copy the code directly. */
308 memcpy(dst_header, src_header, length);
309 }
310
311 /* Clear the signature in the destination code segment. */
312 memset(&(dst_header->hash), 0, sizeof(dst_header->hash));
313
314 if (is_signed) {
315 NV_CHECK_ERROR_CLEANUP(sign_wb_code(seg_address, length,
316 use_zero_key));
317 }
318
319 fail:
320 if (e != NvBootError_Success)
321 printf("WB code not copied to LP0 location! (error=0x%x)\n", e);
322
323 return e;
324 }
OLDNEW
« no previous file with comments | « arch/arm/cpu/arm_cortexa9/tegra2/ap20.c ('k') | arch/arm/cpu/arm_cortexa9/tegra2/warmboot_avp.S » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698