目前面對高性能產品的嵌入式開發中,用SD卡來代替以往的JLINK顯得備受大家喜歡,而且MCU廠家也對以SD卡啟動的支持度越來越大,反而對JLINK不在那么重視(不過依舊保留着)。一些以開發開發板的公司在提供他們自身的bootloader(只是其中一部分是他們自身的代碼而已,下面我會講到這一點)時其原碼並不對外公開,不過大家喜歡的u-boot的原碼是開源的,可是像友善之臂他們的那樣,還得通過他們的superboot來把u-boot二進制代碼載入到LAND FLASH,EMMC等這類外部rom設備中,這也意味着我們還得借助superboot來完成我們u-boot的燒寫,雖然這樣做不是不行,他們不開源源碼但是有二進制可執行文件給咱們用,可對於習慣於開源的人來說,無疑總感覺不爽,因此下面就來介紹如何脫離superboot來完成我們的開發。
跟蹤三星廠商提供的他們修改過的uboot代碼,在主目錄中我們可以看到一個名叫sd—fuse的子目錄,這個子目錄下有一個makefile,查看makefile我們可以知道它的作用是為了編譯產生一個工具mkbl2,這是這個makefile的一部分內容(通過這可以知道是為了生成工具mkbl2):
25 SOURCES = $(OBJECTS:.o=.c)
26
27 all:
28 $(CC) $(CFLAGS) mkbl2 V310-EVT1-mkbl2.c
29 $(CC) $(CFLAGS) sd_fdisk sd_fdisk.c
那么這個mkbl2工具是起什么作用的呢,或者說它能干嘛,通過上面可看到它的信賴源文件V310—EVT1-mkbl2.c,那下面我們當然是來看這個源碼文件嘍:
66 for(i = 0;i < (14 * 1024) - 4;i++)
67 {
68 checksum += (unsigned char)(Buf[i]);
69 }
70 *(unsigned int*)(Buf+i) = checksum;
71
72 fp = fopen(argv[2], "wb");
73 if (fp == NULL)
74 {
75 printf("destination file open error\n");
76 free(Buf);
77 return -1;
78 }
79
80 a = Buf;
81 nbytes = fwrite( a, 1, BufLen, fp);
82
83 if ( nbytes != BufLen )
84 {
85 printf("destination file write error\n");
86 free(Buf);
87 fclose(fp);
88 return -1;
89 }
90
91 free(Buf);
92 fclose(fp);
93
94 return 0;
95 }
上面是其中的部分代碼,可以看到它是從一個指定文件(這個指定文件下面會說到,其實就是個二進制文件)中復制出前14K內容,把前(14*1024-4)=14332字節做個和校驗(checksum)得到一個4字節的校驗碼,再把它放到14332字節之后,輸出一個新的14K的二進制文件。知道了它的作用之后我們繼續跟蹤下去,在sd-fuse目錄下有一個tiny4412的二級子目錄,下面可以看到這些文件:E4412_N.bl1.bin E4412_tzsw.bin fast_fuse.sh sd_fusing.sh,這里有兩個腳本文件:fast_fuse.sh sd_fusing.sh,還兩個由三星提供的二進制文件:E4412_N.bl1.bin E4412_tzsw.bin,sd—fusing.sh是對SD卡的,那下面來看看這個腳本是用來干嘛的:
44 E4412_UBOOT=../../u-boot.bin
45 MKBL2=../mkbl2
46
47 if [ ! -f ${E4412_UBOOT} ]; then
48 echo "Error: u-boot.bin NOT found, please build it & try again."
49 exit -1
50 fi
51
52 if [ ! -f ${MKBL2} ]; then
53 echo "Error: can not find host tool - mkbl2, stop."
54 exit -1
55 fi
56
57 #<make bl2>
58 ${MKBL2} ${E4412_UBOOT} bl2.bin 14336
59
60 ####################################
61 # fusing images
62
63 signed_bl1_position=1
64 bl2_position=17
65 uboot_position=49
66 tzsw_position=705
67
68 #<BL1 fusing>
69 echo "---------------------------------------"
70 echo "BL1 fusing"
71 dd iflag=dsync oflag=dsync if=./E4412_N.bl1.bin of=$1 seek=$signed_bl1_position
72
73 #<BL2 fusing>
74 echo "---------------------------------------"
75 echo "BL2 fusing"
76 dd iflag=dsync oflag=dsync if=./bl2.bin of=$1 seek=$bl2_position
77
78 #<u-boot fusing>
79 echo "---------------------------------------"
80 echo "u-boot fusing"
81 dd iflag=dsync oflag=dsync if=${E4412_UBOOT} of=$1 seek=$uboot_position
82
83 #<TrustZone S/W fusing>
84 echo "---------------------------------------"
85 echo "TrustZone S/W fusing"
86 dd iflag=dsync oflag=dsync if=./E4412_tzsw.bin of=$1 seek=$tzsw_position
87
88 #<flush to disk>
89 sync
90
91 ####################################
92 #<Message Display>
93 echo "---------------------------------------"
94 echo "U-boot image is fused successfully."
95 echo "Eject SD card and insert it again."
分析: 44 E4412_UBOOT=../../u-boot.bin
45 MKBL2=../mkbl2
58 ${MKBL2} ${E4412_UBOOT} bl2.bin 14336
原來之前說到的mkbl2作用是把u-boot.bin來產生一個和校驗,生成文件bl2.bin,下面接着看:
63 signed_bl1_position=1
64 bl2_position=17
65 uboot_position=49
66 tzsw_position=705
71 dd iflag=dsync oflag=dsync if=./E4412_N.bl1.bin of=$1 seek=$signed_bl1_position
76 dd iflag=dsync oflag=dsync if=./bl2.bin of=$1 seek=$bl2_position
81 dd iflag=dsync oflag=dsync if=${E4412_UBOOT} of=$1 seek=$uboot_position
86 dd iflag=dsync oflag=dsync if=./E4412_tzsw.bin of=$1 seek=$tzsw_position
89 sync
可以看到我們通過dd命令(其用法大家可以man一下)把E4412_N.bl1.bin放在SD卡的第1block開始到第17block總共16個block,共8K,(-rw-r--r-- 1 chenpan chenpan 8192 Mar 22 2013 E4412_N.bl1.bin
-rw-r--r-- 1 chenpan chenpan 94208 Mar 22 2013 E4412_tzsw.bin從這也看到了E4412—N.bl1.bin文件大小為8192字節,正好8K),這里會有人問為何不從SD卡的第0block開始,SD卡的前512字節被填充為0,網上說這里原本用來放一些分區信息的。另外的.bin文件也類似的寫進SD卡的指定塊(17-49,49-705,705-),sync是自動填充NUL(0)。
所以我們的SD卡存儲結構就在上面了。大家也可以動手畫出來加深映像。
下面該看看superboot.bin了,我們把它的前560字節打出來:
$hexdump -n 560 Superboot4412.bin
0000000 7bb1 0ac1 3351 33ec 3e84 3b80 2c81 2cf3
0000010 0007 ea00 fffe eaff fffe eaff fffe eaff
0000020 fffe eaff fffe eaff fffe eaff fffe eaff
0000030 fffe eaff 00e8 e59f 0000 e590 1102 e3a0
0000040 0001 e110 0024 0a00 00d8 e59f 0000 e590
0000050 0001 e310 0020 0a00 00cc e59f 0000 e590
0000060 0003 e200 0003 e330 0004 0a00 00bc e59f
0000070 0000 e590 0001 e310 0000 0a00 0016 ea00
0000080 00ac e59f 0000 e590 0003 e200 0003 e330
0000090 0004 0a00 009c e59f 0000 e590 0001 e310
00000a0 0000 0a00 000c ea00 208c e59f 4000 e592
00000b0 2088 e59f 5000 e592 6084 e59f 0006 e154
00000c0 f005 01a0 007c e59f 0000 e590 0007 e200
00000d0 0007 e330 0000 1a00 0010 ea00 0068 e59f
00000e0 1068 e59f 3068 e59f 0001 e150 0003 0a00
00000f0 0003 e151 2004 3490 2004 3481 fffb 3aff
0000100 1050 e59f 2000 e3a0 0001 e153 2004 3483
0000110 fffc 3aff 0010 ea00 fffe eaff 0eb7 ea00
0000120 07b6 ea00 0600 1002 12c0 1002 1188 1002
0000130 1184 1002 1198 1002 1194 1002 0020 0202
0000140 0024 0202 0d10 fcba 1398 1002 2a44 0202
0000150 2a44 0202 2a44 0202 2a44 0202 4070 e92d
0000160 0031 eb00 4070 e6ff 0034 eb00 50ff e200
0000170 01a2 eb00 6000 e1a0 0004 e1a0 00df eb00
0000180 0000 e355 000c 1a00 0036 eb00 0000 e350
0000190 0004 1a00 0078 e59f 1078 e59f 0980 e581
00001a0 f000 e320 fffe eaff 006c e59f 1064 e59f
00001b0 0984 e581 ffd9 ebff 0013 ea00 0000 e356
00001c0 0004 0a00 0054 e59f 1048 e59f 0984 e581
00001d0 ffd2 ebff 000c ea00 015f eb00 0001 e350
00001e0 0004 1a00 0038 e59f 1028 e59f 0984 e581
00001f0 ffca ebff 0004 ea00 0028 e59f 1014 e59f
0000200 0980 e581 f000 e320 fffe eaff 0000 e3a0
0000210 8070 e8bd 0060 dead 0000 1002 50b1 50b1
0000220 50b2 50b1 50b3 50b1 0061 dead 00a8 e59f
0000230
再把E4412_N.bl1.bin的前560字節給打出來:
$hexdump -n 560 E4412_N.bl1.bin
0000000 69a3 18d3 7de9 66b9 6bd1 6ed5 79d4 79a6
0000010 0007 ea00 fffe eaff fffe eaff fffe eaff
0000020 fffe eaff fffe eaff fffe eaff fffe eaff
0000030 fffe eaff 00dc e59f 0000 e590 1102 e3a0
0000040 0001 e110 0024 0a00 00cc e59f 0000 e590
0000050 0001 e310 0020 0a00 00c0 e59f 0000 e590
0000060 0003 e200 0003 e330 0004 0a00 00b0 e59f
0000070 0000 e590 0001 e310 0000 0a00 0016 ea00
0000080 00a0 e59f 0000 e590 0003 e200 0003 e330
0000090 0004 0a00 0090 e59f 0000 e590 0001 e310
00000a0 0000 0a00 000c ea00 2080 e59f 4000 e592
00000b0 207c e59f 5000 e592 6078 e59f 0006 e154
00000c0 f005 01a0 0070 e59f 0000 e590 0007 e200
00000d0 0007 e330 0000 1a00 07c8 ea00 005c e59f
00000e0 105c e59f 305c e59f 0001 e150 0003 0a00
00000f0 0003 e151 2004 3490 2004 3481 fffb 3aff
0000100 1044 e59f 2000 e3a0 0001 e153 2004 3483
0000110 fffc 3aff 002b ea00 0600 1002 12c0 1002
0000120 1188 1002 1184 1002 1198 1002 1194 1002
0000130 0020 0202 0024 0202 0d10 fcba 1398 1002
0000140 2aa4 0202 2aa4 0202 2aa4 0202 2aa4 0202
0000150 1201 e3a0 000c e591 0000 e350 0002 1a00
0000160 1000 e3a0 2104 e59f 1008 e582 ff1e e12f
0000170 00fc e59f 0700 e590 0702 e380 0b02 e380
0000180 10ec e59f 0700 e581 0001 e1a0 0704 e590
0000190 0402 e380 0040 e380 0704 e581 0001 e1a0
00001a0 0900 e590 0402 e380 0080 e380 0900 e581
00001b0 0907 e301 1719 e281 0008 e581 1842 e281
00001c0 0008 e581 ff1e e12f 4070 e92d ffdf ebff
00001d0 ffe6 ebff 002b eb00 4070 e6ff 002e eb00
00001e0 50ff e200 019d eb00 6000 e1a0 0004 e1a0
00001f0 00da eb00 0000 e355 000a 1a00 0030 eb00
0000200 0000 e350 0004 1a00 0068 e59f 1068 e59f
0000210 0980 e581 f000 e320 fffe eaff 005c e59f
0000220 ff30 e12f 000f ea00 0000 e356 0002 0a00
0000230
大家是不是發現了什么了?對,從第16字節開始一直到512字節這些指令操作碼是一樣的,也就是說superboot的起始位置也是用了三星給的啟動代碼,superboot是把BL1及superboot結合在一起了,如果有哪位arm-gnu匯編大神非常想知道superboot的具體工作,可以去反匯編(arm-linux-objdump -D -b binary -m arm Superboot4412.bin > superboot.asm &&vim superboot.asm ),或者通過網絡入侵友善之臂的網站去找(純屬開個玩笑而已,這可是犯法的事咱不干)。
好了,今天是1/10這到這里吧!歡迎各路大神來指點錯誤,謝謝大家!