原文发在我的bloghttp://blog.csersoft.net/archives/196
前言
前几天使用UBoot恢复mtd分区时因为误操作导致flash全部被擦除。这下设备上电时连StartCode都跑不了。写内存跑StartCode都不行外部设备没有初始化无法访问DRAM> mdw 0x82000000
data abort at 0x82000000, dfsr = 0x00001008
可以看到原本是放置StartCode的地址现在都无法访问。折腾了几天大致成功的利用JTAG完成硬件初步初始化并且可以加载StartCode到内存并成功运行了。
问题解决思路
想要写内存来运行代码就必须对内存进行初始化操作。但这个初始化操作应该都是StartCode里做的。现在StartCode都跑不起更别说写内存了。
如果用JTAG来模拟StartCode的初始操作的话也不太现实毕竟100多KB的代码分析起来就够累人了别说模拟了。但是如果能找到一个平衡点模拟少量的操作让硬件环境刚好够我利用来跑StartCode这样实现还是比较容易的。
在网上查了很多关于ARM处理器复位时的流程和低级bootloader做的工作相关的资料。大致感觉有路可走
一般对于采用非可直接寻址的存储设备(Nand Flash)来引导的话CPU内部会有一个bootrombootrom在上电时会从非可直接寻址的存储设备的固定位置装载固定大小的内容到片内SRAM比如从Nand Flash的0地址读取2KB内容到片内SRAM然后设置pc过去并运行。这很小的一部分bootloader就会做简单的初始化操作然后读取完整的bootloader到内存中的指定位置并运行。
逆向分析StartCode
StartCode的一开始就是ARM经典的中断向量表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24seg000:00000000;---------------------------------------------------------------------------
seg000:00000000Bsub_5C
seg000:00000004;---------------------------------------------------------------------------
seg000:00000004LDRPC,=sub_820003A0
seg000:00000008;---------------------------------------------------------------------------
seg000:00000008LDRPC,=loc_82000400
seg000:0000000C;---------------------------------------------------------------------------
seg000:0000000CLDRPC,=loc_82000460
seg000:00000010;---------------------------------------------------------------------------
seg000:00000010LDRPC,=loc_820004C0
seg000:00000014;---------------------------------------------------------------------------
seg000:00000014LDRPC,=loc_82000520
seg000:00000018;---------------------------------------------------------------------------
seg000:00000018LDRPC,=loc_82000580
seg000:0000001C;---------------------------------------------------------------------------
seg000:0000001CLDRPC,=loc_820005E0
seg000:0000001C;---------------------------------------------------------------------------
seg000:00000020off_20DCDsub_820003A0;DATAXREF:seg000:00000004
seg000:00000024off_24DCDloc_82000400;DATAXREF:seg000:00000008
seg000:00000028off_28DCDloc_82000460;DATAXREF:seg000:0000000C
seg000:0000002Coff_2CDCDloc_820004C0;DATAXREF:seg000:00000010
seg000:00000030off_30DCDloc_82000520;DATAXREF:seg000:00000014
seg000:00000034off_34DCDloc_82000580;DATAXREF:seg000:00000018
seg000:00000038off_38DCDloc_820005E0;DATAXREF:seg000:0000001C
第一个中断向量就是偏移0的复位中断向量。CPU在复位时会从这里开始执行复位中断向量直接跳到0x5C处处理reset中断的实际代码位置。
在StartCode的0x5C处IDA Pro就可以直接F5了以下为还原的伪代码部分地方还原的有问题手工修改过
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119voidsub_5C()
{
unsignedint_R0;// r0@1
signedintv5;// r3@1
signedintv6;// r0@1
signedintv7;// r1@2
_DWORD*v8;// r2@14
int(*v9)();// r0@16
void(__noreturn*v10)();// r1@16
intv11;// r3@17
intv12;// r4@17
intv13;// r5@17
intv14;// r6@17
intv15;// r7@17
intv16;// r8@17
intv17;// r9@17
intv18;// r10@17
//enter Supervisor mode
_R0=__get_CPSR()&0xFFFFFFE0|0xD3;
__asm{MSRCPSR_cf,R0}
//arm cp15 coprocessor
__mcr(15,0,0,8,7,0);
__mcr(15,0,0,7,5,0);
__mcr(15,2,0,0,0,0);
v5=((unsignedint)__mrc(15,1,0,0,0)>>13)&0x1FF;
v6=0;
do
{
v7=0;
do
__mcr(15,0,(v6<<30)|32*v7++,7,6,2);
while(v7<=v5);
++v6;
}
while(v6<4);
if(__mrc(15,0,0,0,5)&0xF)
gotoLABEL_25;
__mcr(15,0,__mrc(15,0,1,0,0)&0xFFFFDFF8|0x802,1,0,0);
if(!(__mrc(15,0,0,0,5)&0xF))
{
sub_6EC();
sub_700();
sub_710();
}
__mcr(15,0,__mrc(15,0,1,0,0)|0x1000,1,0,0);
v10A30004=853;
v10A20100|=2u;
sub_FAD4();
dword_1010007C=-1;
dword_1010008C=-1;
dword_1010012C=-1;
dword_10100130=0xFE7FFFFF;
dword_10100138|=0x7Fu;
dword_10100140|=0x80000000;
if(dword_10100800==0x51152100)
{
if((dword_10100190&1)==1)
dword_1010005C=0x8103844D;
dword_1010005C=0x8103444D;
}
while((dword_10100038&0x10000)!=0x10000)
;
while((dword_10100038&0x40000)!=0x40000)
;
dword_1010013C=dword_1010013C&0xFFFFFFE3|0x10;
sub_FCD4();
dword_1010013C&=0xFFFFF3FF;
dword_10100138&=0xFFDFFFFF;
dword_10100138&=0xFFF7FFFF;
dword_10100054=0xFFFFFFE0;
dword_10100050=0x7FF00;
dword_10100000|=4u;
while((*v8&4)!=4)
;
sub_FAF4();
sub_FBD8();
sub_FED4();
//判断装载地址准备自搬移
v9=sub_0;
v10=sub_82000000;
if((char*)sub_0!=(char*)sub_82000000)
{
do
{
v11=*(_DWORD*)v9;
v12=*((_DWORD*)v9+1);
v13=*((_DWORD*)v9+2);
v14=*((_DWORD*)v9+3);
v15=*((_DWORD*)v9+4);
v16=*((_DWORD*)v9+5);
v17=*((_DWORD*)v9+6);
v18=*((_DWORD*)v9+7);
v9=(int(*)())((char*)v9+32);
*(_DWORD*)v10=v11;
*((_DWORD*)v10+1)=v12;
*((_DWORD*)v10+2)=v13;
*((_DWORD*)v10+3)=v14;
*((_DWORD*)v10+4)=v15;
*((_DWORD*)v10+5)=v16;
*((_DWORD*)v10+6)=v17;
*((_DWORD*)v10+7)=v18;
v10=(void(__noreturn*)())((char*)v10+32);
}
while((signedint)v9<=(signedint)&unk_1F1B4);
if(dword_10100800!=0x51152100)
LABEL_21:
JUMPOUT(&loc_820002C8);
if(__mrc(15,0,0,0,5)&0xF)
{
LABEL_25:
while(3538!=dword_10100120)
;
gotoLABEL_21;
}
}
JUMPOUT(&loc_82000304);
}
可以看出在v9 = sub_0;
v10 = sub_82000000;
之后就开始代码的自搬移了。其中v9是程序装载的位置v10是StartCode应该被放置的地址。
也就是说只要通过JTAG完成这两句代码之前StartCode所做的操作就可以使用JTAG访问外部RAM了起始地址大约在0x80000000。
使用TCL脚本模拟实现初始化操作
好在OpenOCD支持tcl脚本大概熟悉了一下tcl的语法并结合逆向的数据写了个模拟初始化操作的脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486#
# Hisilicon SD5115 (T?)
#
# Author : CserSoft
# Version : 1.2.2
#
transportselectjtag
if{[infoexistsCHIPNAME]}{
set_CHIPNAME$CHIPNAME
}else{
set_CHIPNAMEsd5115
}
if{[infoexistsCPUTAPID]}{
set_CPU_TAPID$CPUTAPID
}else{
set_CPU_TAPID0x4ba00477
}
if{[infoexistsENDIAN]}{
set_ENDIAN$ENDIAN
}else{
# this defaults to a bigendian
set_ENDIANlittle
}
if{[infoexistsETB_TAPID]}{
set_ETB_TAPID$ETB_TAPID
}else{
set_ETB_TAPID0x410CF231
}
jtagnewtap$_CHIPNAMEcpu-irlen4-ircapture0x1-irmask0xf-expected-id$_CPU_TAPID
# jtag newtap $_CHIPNAME etb -irlen 4 -expected-id $_ETB_TAPID
set_TARGETNAME$_CHIPNAME.cpu
targetcreate$_TARGETNAMEcortex_a-endian$_ENDIAN-chain-position$_TARGETNAME
# etm_dummy config $_TARGETNAME
# etb config $_TARGETNAME $_CHIPNAME.etb
procsd5115_dbginit{target}{
cortex_adbginit
}
procgetmem32{addr}{
mem2arrayatmp32$addr1
return[lindex$atmp1]
}
procsetmem32{addrvalue}{
mwwphys$addr$value1
}
procandmem32{addrvalue}{
setvmem[getmem32$addr]
return[expr$vmem&$value]
}
procandmem32w{addrvalue}{
setvmem[expr[getmem32$addr]&$value]
mwwphys$addr$vmem1
return$vmem
}
procormem32{addrvalue}{
setvmem[getmem32$addr]
return[expr$vmem|$value]
}
procormem32w{addrvalue}{
setvmem[expr[getmem32$addr]|$value]
mwwphys$addr$vmem1
return$vmem
}
procsd5115_startcode_offset_0x6EC{}{
andmem32w0x101800000xFFFFFFFE
}
procsd5115_startcode_offset_0x700{}{
mwwphys0x1018000C0xFFFFFFFF1
}
procsd5115_startcode_offset_0x710{}{
ormem32w0x101800540xFF
ormem32w0x101800000x1
}
procsd5115_startcode_offset_0xFAD4{}{
setmem320x10100144[expr[andmem320x101001440xFFF803FF]|0x400]
}
procsd5115_startcode_offset_0xFAF4{}{
setvcpuid[getmem320x10100800]
if{$vcpuid==0x51151100}{
ormem32w0x130000000x80000
ormem32w0x101060080xC0
ormem32w0x101060080x300
}elseif{$vcpuid==0x51152100}{
ormem32w0x130000000x60000
ormem32w0x101080080xF0
}else{
ormem32w0x130001C80x100
ormem32w0x101060080xC00
andmem32w0x130000000xFFFFFFFB
andmem32w0x130001C80xFFFFFFDF
ormem32w0x101060080x3000
andmem32w0x130000000xFFFDFFFF
andmem32w0x130001C80xFFFFFFBF
}
}
procsd5115_startcode_offset_0xFBD8{}{
setvcpuid[getmem320x10100800]
if{$vcpuid!=0x51151100}{
if{$vcpuid==0x51152100}{
setmem320x104005000x1FFF800
andmem32w0x101001340xFFFFFFFC
andmem32w0x101070080xDDFFFFFF
ormem32w0x101070040x22000000
ormem32w0x101070000x22000000
andmem32w0x101080080xFFF7FFFF
ormem32w0x101080040x80000
ormem32w0x101080000x80000
andmem32w0x101001440x3FFFFFFF
}else{
setmem320x104005000x1FFF800
andmem32w0x101001340xFFFFFFFC
ormem32w0x101070040x18000
andmem32w0x101070000xFFFE7FFF
ormem32w0x101070000x18000
andmem32w0x1300016C0xFFFFFFFC
}
}
}
procsd5115_startcode_offset_0xFCD4{}{
setvcpuid[getmem320x10100800]
if{$vcpuid==0x51151100}{
andmem32w0x1010012C0xFFBFFFFF
andmem32w0x101001380xFFFFFFBF
ormem32w0x101000800x9
andmem32w0x1010013C0xFFFFEFFF
setmem320x1010005C0x81020248
while{[andmem320x101000380x10000]!=0x10000}{sleep1}
ormem32w0x1010007C0x9
ormem32w0x101001480x2
ormem32w0x1010012C0x400000
ormem32w0x101001380x40
}elseif{$vcpuid==0x51152100}{
if{[andmem320x101001901]==1}{
andmem32w0x1010012C0xFFBFFFFF
andmem32w0x101001380xFFFFFFBF
ormem32w0x101000800x9
andmem32w0x101001440xFEFFFFFF
andmem32w0x101001400xFFFFCFFF
ormem32w0x101001400x40000000
setmem320x101000740x81028249
while{[andmem320x101000380x40000]!=0x40000}{sleep1}
ormem32w0x1010007C0x9
ormem32w0x101001480x2
ormem32w0x1010012C0x400000
ormem32w0x101001380x40
}else{
while{[andmem320x101000380x20000]!=0x20000}{sleep1}
}
}else{
andmem32w0x1010012C0xFFBFFFFF
andmem32w0x101001380xFFFFFFBF
ormem32w0x101000800x9
setmem320x1010011C0x81028648
while{[andmem320x101000380x20000]!=0x20000}{sleep1}
ormem32w0x1010007C0x9
ormem32w0x101001480x2
ormem32w0x1010012C0x400000
ormem32w0x101001380x40
}
}
procsd5115_startcode_offset_0xFED4{}{
setvcpuid[getmem320x10100800]
if{$vcpuid==0x51151100}{
setmem320x101020101
setmem320x1010201C0x8DF40630
setmem320x101020200x10184
setmem320x1010202C0x132
setmem320x101020400x80000000
setmem320x101020500x62330A08
setmem320x101020540x7F525616
setmem320x1010205C0x4BE58352
setmem320x101020F41
setmem320x101020580x6230A000
setmem320x101020040
while{[andmem320x101020004]!=0}{sleep1}
setmem320x101024040x80000000
while{[andmem320x101024101]!=1}{sleep1}
setmem320x101024180xDC000
setmem320x101025840x5D
setmem320x1010240C0x3008401
setmem320x101024440x48B
setmem320x101024480x51106644
setmem320x1010244C0x1A81629A
setmem320x101024500x100220C8
setmem320x101024540x1520
setmem320x101024586
setmem320x1010245C0
setmem320x101024600
setmem320x101025C00x44000887
setmem320x101024400xF008003E
setmem320x101024680x1001541
setmem320x101024040xFFF3
while{[andmem320x101024100x80000FFF]!=0x80000FFF}{sleep1}
setmem320x101020580x6230A05F
setmem320x101020200x410185
setmem320x1010201C0x8DF40630
setmem320x101022000x305133
setmem320x101022040x3062CC
}elseif{$vcpuid==0x51152100}{
if{[andmem320x101001901]==1}{
setmem320x101020101
setmem320x1010201C0x80000600
setmem320x101020200x584
setmem320x1010202C0x142
setmem320x101020400x80000000
setmem320x101020500x63440E0A
setmem320x101020540xFF526720
setmem320x101020580x6240A000
setmem320x1010205C0xFFDFF5F2
setmem320x101020F40x21
setmem320x101020AC0x3000501
setmem320x101020040
while{[andmem320x101020004]!=0}{sleep1}
setmem320x101024040x80000000
while{[andmem320x101024101]!=1}{sleep1}
setmem320x101024180x5C000
setmem320x1010248C0xF01E78
setmem320x1010241C0x1F40FA10
setmem320x101024200x61A808CA
setmem320x101024280xC83D090
setmem320x1010242C0x1F4186A0
setmem320x101024440x48B
setmem320x101024480x6D538844
setmem320x1010244C0x22820282
setmem320x101024500x1002EA00
setmem320x101024540x1930
setmem320x101024580x42
setmem320x1010245C8
setmem320x101024600
setmem320x101024640x210000
setmem320x101024680x210035C3
setmem320x101025840x2D
setmem320x101025C00x44000E81
setmem320x101026000x44000E81
setmem320x101024400xF000603E
setmem320x101024040xFFF3
while{[andmem320x101024101]!=1}{sleep1}
setmem320x101020580x6240A079
setmem320x101022000x304132
setmem320x101022040x306132
setmem320x101022080x304066
setmem320x101022100x306132
}else{
setmem320x101020101
setmem320x1010201C0x80000601
setmem320x101020200x580
setmem320x1010202C0x142
setmem320x101020400x80000000
setmem320x101020500xC466150F
setmem320x101020540xFF545540
setmem320x101020580x84610000
setmem320x1010205C0xFFDFF4F4
setmem320x101020F40x21
setmem320x101020AC0x3000501
setmem320x101020040
while{[andmem320x101020004]!=0}{sleep1}
setmem320x101024040x80000000
while{[andmem320x101024101]!=1}{sleep1}
setmem320x101024180x5C000
setmem320x1010248C0xF01860
setmem320x1010241C0x1900C810
setmem320x101024200x4E200708
setmem320x101024280xA030D40
setmem320x1010242C0x19013880
setmem320x101024440x48B
setmem320x101024480x550F6644
setmem320x1010244C0x22820202
setmem320x101024500x1002EA00
setmem320x101024540x1510
setmem320x101024580x42
setmem320x1010245C0
setmem320x101024600
setmem320x101024640x210000
setmem320x101024680x210035C3
setmem320x101025840x2D
setmem320x101025C00x44000E81
setmem320x101026000x44000E81
setmem320x101024400xF008603E
setmem320x101024040xFFF3
while{[andmem320x101024101]!=1}{sleep1}
setmem320x101020580x846100C3
setmem320x101022000x304132
setmem320x101022040x306132
setmem320x101022080x304066
setmem320x101022100x306132
}
}else{
setmem320x101020101
setmem320x1010201C0xE92E0601
setmem320x101020200x1F180
setmem320x1010202C0x132
setmem320x101020400x80000000
setmem320x101020500xC466130E
setmem320x101020540xFF535625
setmem320x1010205C0x7E58484
setmem320x101020F41
setmem320x101020580x74511000
setmem320x101020AC0x3000501
setmem320x101020040
while{[andmem320x101020004]!=0}{sleep1}
setmem320x101024040x80000000
while{[andmem320x101024101]!=1}{sleep1}
setmem320x101024180xDC000
setmem320x1010240C0x3008401
setmem320x101024440x48B
setmem320x101024480x4D0E6644
setmem320x1010244C0x1A812A30
setmem320x101024500x1001A0C8
setmem320x101024540x1320
setmem320x101024580x42
setmem320x1010245C0
setmem320x101024600
setmem320x101024680x11001547
setmem320x101025C00x44000887
setmem320x101026000x44000E81
setmem320x101024400xF008003E
setmem320x101025840x1D
setmem320x101024040xFFF3
while{[andmem320x101024100x80000FFF]!=0x80000FFF}{sleep1}
setmem320x101020580x7450F09E
setmem320x101020200x40EF01
setmem320x101020F80
setmem320x101022000x305133
setmem320x101022040x306266
setmem320x101022080x306066
setmem320x1010220C0
setmem320x1010201C0xB9D60601
}
}
procsd5115_hwinit{}{
halt
#enter Supervisor mode
regcpsr0x1D3
armmcr1508700
armmcr1507500
armmcr1520000
setv5[expr([armmrc151000]>>13)&0x1ff]
setv60
while{$v6<4}{
setv70
while{$v7<=$v5}{
setvtmp[expr($v6<<30)|32*$v7]
setv7[incr$v7]
armmcr150762$vtmp
}
setv6[incr$v6]
}
if{[expr[armmrc150005]&0xf]!=0}{
echo"Error 1 !"
return
}
armmcr150100[expr[armmrc150001]&0xFFFFDFF8|0x802]
if{[expr[armmrc150005]&0xf]!=0}{
sd5115_startcode_offset_0x6EC
sd5115_startcode_offset_0x700
sd5115_startcode_offset_0x710
}
armmcr150100[expr[armmrc150100]|0x1000]
setmem320x10A300040x00000355
ormem32w0x10A201000x2
sd5115_startcode_offset_0xFAD4
setmem320x1010007C0xFFFFFFFF
setmem320x1010008C0xFFFFFFFF
setmem320x1010012C0xFFFFFFFF
setmem320x101001300xFE7FFFFF
ormem32w0x101001380x7F
ormem32w0x101001400x80000000
setvcpuid[getmem320x10100800]
if{$vcpuid==0x51152100}{
if{[expr[getmem320x10100190]&1]==1}{
mwwphys0x1010005C0x8103844D1
}
mwwphys0x1010005C0x8103444D1
}
while{[andmem320x101000380x10000]!=0x10000}{sleep1}
while{[andmem320x101000380x40000]!=0x40000}{sleep1}
setmem320x1010013C[expr[andmem320x1010013C0xFFFFFFE3]|0x10]
sd5115_startcode_offset_0xFCD4
andmem32w0x1010013C0xFFFFF3FF
andmem32w0x101001380xFFDFFFFF
andmem32w0x101001380xFFF7FFFF
setmem320x101000540xFFFFFFE0
setmem320x101000500x7FF00
ormem32w0x101000000x4
while{[andmem320x101000000x4]!=0x4}{sleep1}
sd5115_startcode_offset_0xFAF4
sd5115_startcode_offset_0xFBD8
sd5115_startcode_offset_0xFED4
echo"Hardware initialization is complete!"
}
$_TARGETNAMEconfigure-eventreset-assert-post"sd5115_dbginit $_TARGETNAME"
# init
# dap apsel 1
使用JTAG完成基本硬件初始化
为了确保初始化准确无误需要保证CPU上电时完全无法找到可以引导的代码。
因为我之前清空flash时也曾尝试立刻刷回StartCode可惜不知什么原因只写入了2KB的StartCode这样仍然无法完成基本的初始化。但不清楚这2KB的代码完成了哪些操作所以一个办法就是先将flash的CE#CE#这种后面带#字的引脚都是低电平有效与3.3V短接最好是能与输出3.3V的GPIO短接与3.3V的VCC短接电流可能较大不知是否有不良影响再给板子上电。HG8245H的CE#引脚在板子背面电源led附近有个上拉电阻R1542可以在这里短接。
CPU上电后在OpenOCD的telnet里执行上面脚本提供的sd5115_hwinit函数等看到输出Hardware initialization is complete!
字样的提示后把之前dump出来的StartCode写入内存并运行
1halt ; load_image binary/mtd0.bin 0x82000000 ; resume 0x82000000
这时应该可以看见UART里输出了久违的StartCode信息HuaWei StartCode 2012.02 (R13C10 Apr 22 2014 – 18:06:02)
NAND: Nand(Hardware): 128 MiB
startcode select the uboot to load
the high RAM is :8080103c
startcode uboot boot count:-1
Slave struct initializtion success!!
Use the UbootA to load first
Start from UbootA ERROR, Change to UbootB
Both UbootA and UbootB are wrong, load it by JTAG!
补充
新版本的OpenOCD配置文件见https://github.com/csersoft/hi_sd5115_openocd_config
最新sd5115 openocd 配置文件见https://github.com/csersoft/hi_sd5115_openocd_config
安卓应用层抓包通杀脚本发布《高研班》2021年3月班开始招生
上传的附件
hi_sd5115_jtag.zip
2.61kb28次下载
blog.csersoft.net-华为HG8245H救砖番外篇之利用JTAG完成硬件初始化.pdf
154.44kb29次下载