Pure Linux OTP-Key Security Boot Flow SOP
1. SECURITY BOOT介绍¶
1.1. 概述¶
Security Boot需要做的工作总体上包括签章(或加密+签章)和验签(或验签+解密)两大部分,验签即签章的验证,其中加密和解密为可选,用户可根据自身需求取舍。
一般情况下加密是为了防止信息被泄露,而验签是为了防止信息被篡改。加密(详见加密Security Boot流程章节)和签章(详见签章介绍部分)的工作将使用脚本完成,而验签和解密的工作将由固件中Software完成。Security Boot的验签和解密总体流程如下。
图1-1 验签和解密总体流程
1.1.1. 秘钥介绍
从秘钥使用的角度看,签章和验签分别使用了RSA Private Key
和RSA Public Key
,加密和解密使用同一把AES Key
。
-
验签流程中所用的
RSA Public Key
有两把。第一把为
OTP Key
,该把Key会在系统Power On后,Hardware会自动从OTP中载入,用来做签章验证的动作,这边Software是无法介入的。而OTP Key的内容,可以通过Linux Tool或U-Boot的Command Line烧录至OTP的指定地址中。第二把为
CUST Key
,该Key会嵌在IPL和IPL_CUST的bin文件中,通过Software在整个boot flow中用来做签章验证的动作。 -
验签流程中所用的
AES Key
为OTP Key
,该把Key使用之前需要烧录到OTP存储单元中,在使用的时候,由Hardware载入到crypto engine进行使用,可以在整个boot flow中用来做AES解密的动作。OTP AES Key
的内容由用户自定义,所以由用户维护。
1.1.2. 流程介绍
-
Authenticate IPL by OTP Key-RSA
该流程为ROM code从OTP中读取RSA Public Key后,对IPL进行签章的验证,如图1-1的步骤1。由于OTP的RSA Public Key可以进行Write Lock动作(后面章节会详细提及),阻止再次被写,所以OTP的RSA Public Key可以做到不被替换,从而保证了IPL不会被篡改。
-
Authenticate IPL_CUST by IPL's CUST Key-RSA
该流程为IPL读取事先嵌在IPL的CUST RSA Public Key后,对IPL_CUST进行签章的验证,如图1-1的步骤2。由于IPL不会被篡改,所以保证了嵌在IPL的CUST RSA Public Key不会被篡改,从而保证了IPL_CUST也不会被篡改。
-
Authenticate U-Boot/kernel by IPL_CUST's CUST Key-RSA
该流程为IPL_CUST读取事先嵌在IPL_CUST的CUST RSA Public Key后,对U-Boot进行签章的验证,如图1-1的步骤3。同样U-Boot也读取这把Key对下一阶段的Linux Kernel进行签章验证,如图1-1的步骤5。
-
Decrypt U-Boot/kernel by OTP Key–AES
如果开启加密机制,U-Boot及Linux Kernel会通过AES128(ECB)来做加密动作,在Boot流程中,IPL_CUST使用OTP中事先烧录好的AES Key对U-Boot执行解密动作,同样U-Boot也对Linux Kernel执行解密动作,如图1-1的步骤4、6。
1.2. OTP Key¶
1.2.1. OTP RSA Key
OTP Key
为ROM code
用来验证IPL的签章所使用的RSA Public Key
,由N-key
及E-key组成,需通过Linux Tool或在Uboot下预先烧录到OTP中。在开机时,则会由Hardware自动载入。
OTP Key
相应的地址空间只能烧写一次,此外,OTP Key
带有Read Lock
和Write Lock
功能,来防止OTP Key
被非法读取和篡改(烧写OTP RSA Key
及其Lock相关内容后面章节会提及)。
1.2.2. OTP AES Key
OTP AES Key
长度为128bit,若使用"签章+加密"则会用到OTP AES Key
,需要在使用之前就将Key烧录于OTP存储单元中(烧写OTP AES Key
相关内容后面章节会提及)。
1.3. CUST Key¶
CUST Key
可由RSA Public Key
(RSA-2048,长度为2048 bit)及AES Key
(ECB-128,长度为128 bit)所组成,在签章过程中,IPL的bin文件和IPL_CUST的bin文件都会嵌入RSA Public Key
,bin文件组成结构变化情况分别如下图。
1.3.1. IPL结构
图1-2 IPL结构
1.3.2. IPL_CUST结构
图1-3 IPL_CUST结构
1.4. Boot Flow结构¶
Boot Flow请参考下图,该图为从ROM到Linux Kernel的Boot Flow结构,其中Signature为签章数据部分,每个Flow的Signature均会嵌入到相应bin文件的最后,每个Flow均包含Get Key和Authenticate的动作直到Linux Kernel,部分Flow支持解密(是否开启解密取决于需求)。Get Key有三种,OTP RSA Key和OTP AES Key均由Hardware获取,CUST RSA Key由Software获取。需要注意的是IPL_CUST是Insert CUST RSA Key后才进行签章的,所以其Signature嵌入在CUST RSA Key后面。
图1-4 Boot Flow结构
1.5. OTP开启Security Boot¶
当烧录完OTP Key后,真正启动Security Boot必须要烧录OTP_Secure_Boot相应的Register栏位(OTP烧录方法后面章节会详细提及),将该栏位烧录为0xFF,则会启动OTP的Security Boot(注:开启后无法关闭,每次启动都将会强制走Security Boot flow)。
1.6. 普通Security Boot流程¶
如下所示,Generate Signature是在local端执行,这部分目前方案是使用Python脚本完成(后面章节会详细提及),先对Image file进行SHA-256的计算,生成Digest,再通过RSA-2048做加密动作,最后生成256Bytes的signature,再将signature嵌入至Image后端。
Verify Signature是在boot flow中执行,各阶段的boot code会对下一段的Image进行SHA-256计算,生成Digest,并取出signature来做RSA-2048的解密生成Digest',然后对比Digest和Digest',若对比一致,则Verify success,否则Verify fail。
图1-5 普通Security Boot流程
1.7. 加密Security Boot流程¶
如下所示,Generate Signature是在local端执行,这部分目前方案是使用Python脚本完成(后面章节会详细提及),一开始会先将Image file通过AES-128(ECB)加密成Cipher file,再对Cipher file进行SHA-256计算,生成Digest,再通过RSA-2048做加密动作,最后生成256Bytes的signature,再将signature嵌入至Image后端。
Verify Signature是在boot flow中,各阶段的boot code会对下一段的Imag进行SHA-256计算,生成Digest,并取出Signature来做RSA-2048的解密后,生成Digest',最后对比Digest和Digest'。如对比成功,则对Cipher file进行AES-128(ECB) 解密的动作,最后解密为能开机的image。
图1-6 加密Security Boot流程
2. OTP Key读写操作说明¶
2.1. 生成 RSA Key¶
通过openssl来生成RSA Key。相关的命令操作,请参考如下:
-
Generate Private Key
-
openssl genrsa -out private.pem 2048
-
Generate Public Key
-
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
2.2. 使用U-BOOT烧录OTP¶
注:OTP只能烧写一次,一旦烧写则无法清除和重烧,请在确认需要的场合下执行烧写动作!
2.2.1. 生成U-Boot Command Scripts
通过Tool (key_proc.py
) 可产生U-Boot command scripts
来方便通过U-Boot来将RSA-Public Key烧录至OTP指定位置上。
./key_proc.py --exportkey --rsa=public.pem
exportkey: 将public.pem 转换成rsaKey.bin的binary file
rsa: 输入openssl所生成的public key (public.pem)
执行该command后会生成的文件如下:
-
rsaKey.bin——RSA Public N-Key binary file
-
rsaKey.txt——Otp Command List for write RSA Public N-Key rsaKey.txt,会列出烧录Key的Uboot command list,可以直接使用该command list来进行烧录。
注:RSA N-Key有4行command,要分四次执行,不可一次执行4行。
rsaKey.bin:
rsaKey.txt:
2.2.2. 启动Secure Boot
通过烧录OTP中的Secure Boot的栏位来启动Secure boot功能,一旦启动Secue Boot后,在ROM阶段就会开始进行IPL的签章验证。启动方式可通过烧录OTP_SECURE_BOOT (0x2)。
这边需确认是否有正确开启Secure Boot,在未开启前,其Boot行为如下:
-
[普通安全boot流程] Boot flow不会对签章进行验证,所以是可以完成整个Boot流程。
-
[加密安全boot流程] Boot flow不会对签章进行验证,也不会对Image进行解密,所以会无法正常开机。
2.3. OTP Command Format¶
如下图,列出在UBOOT下执行OTP烧录的两个COMMAND,分别能对OTP进行读写的动作。
WRITE COMMAND:
READ COMMAND:
2.4. OTP Command Support List for IC Pudding¶
2.4.1. OTP_RSA_N (0x0)
该Command被使用来存取OTP中的RSA Public N-Key
,总共包含256-Bytes的OTP位置。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otp -w 0x0 offset writedata
READ COMMAND:
otpctrl -r 0x0
2.4.2. OTP_RSA_E (0x1)
该Command被使用来存取OTP中的RSA Public E-Key,总共包含4-Bytes的OTP位置。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x1 0x0 0x01000100
READ COMMAND:
otpctrl -r 0x1
2.4.3. OTP_SECURE_BOOT (0x2)
该Command被使用来启动secure boot,设置为0xFF表示启动secure boot。在设置完该Command后,须于下次启动才会生效。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x2 0x0 0xFF
READ COMMAND:
otpctrl -r 0x2
2.4.4. OTP_RSA_KEY_LOCK_AND_BLOCK (0x3)
该Command被使用来对OTP内的RSA Public Key
栏位进行LOCK跟BLOCK的动作。LOCK表示无法更改RSA Public Key
的内容值,而BLOCK则表示SW无法读出位于OTP内的Public Key
。在设置完该Command后,须于下次启动才会生效。
-
LOCK
WRITE COMMAND:
otpctrl -w 0x3 0x0 0x04
READ COMMAND:
otpctrl -r 0x3
-
BLOCK
WRITE COMMAND:
otpctrl -w 0x3 0x0 0x10
READ COMMAND:
otpctrl -r 0x3
2.4.5. OTP_AES_KEY (0x4)
该Command被使用来存取OTP中的AES Key,总共包含16-Bytes的OTP位置。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x0 offset writedata
READ COMMAND:
otpctrl -r 0x4
Example:
制作AES KEY: echo '000102030405060708090A0B0C0D0E0F' | xxd -r -ps > aesKey.bin otpctrl -w 0x4 0x0 0x03020100 otpctrl -w 0x4 0x4 0x07060504 otpctrl -w 0x4 0x8 0x0B0A0908 otpctrl -w 0x4 0xC 0x0F0E0D0C
2.4.6. OTP_AES_KEY_LOCK_AND_BLOCK (0x6)
该Command被使用来对OTP内的AES Key栏位进行LOCK跟BLOCK的动作。LOCK表示无法更改OTP内的AES Key,而BLOCK则表示SW无法读出OTP内的AES Key。在设置完该Command后,须于下次启动才会生效。
-
LOCK
WRITE COMMAND:
otpctrl -w 0x6 0x0 0x01
READ COMMAND:
otpctrl -r 0x6
-
BLOCK
WRITE COMMAND:
otpctrl -w 0x6 0x0 0x04
READ COMMAND:
otpctrl -r 0x6
2.4.7. ERROR CODE
FF01: 无效的COMMAND
FF02: 无效的OTP地址
FF03: 无效的OTP执行许可证
2.5. OTP Command Support List for IC Tiramisu¶
2.5.1. OTP_RSA_N (0x0)
该Command被使用来存取OTP中的RSA Public N-Key,总共包含256-Bytes的OTP位置。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otp -w 0x0 offset writedata
READ COMMAND:
otpctrl -r 0x0
2.5.2. OTP_RSA_E (0x1)
该Command被使用来存取OTP中的RSA Public E-Key,总共包含4-Bytes的OTP位置。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x1 0x0 0x01000100
READ COMMAND:
otpctrl -r 0x1
2.5.3. OTP_SECURE_BOOT (0x2)
该Command被使用来启动secure boot,设置为0xFF表示启动secure boot。在设置完该Command后,须于下次启动才会生效。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x2 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x2
2.5.4. OTP_RSA_KEY_LOCK (0x3)
该Command被使用来对OTP内的RSA Public Key栏位进行LOCK的动作。LOCK表示无法更改OTP内的RSA Public Key。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x3 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x3
2.5.5. OTP_RSA_KEY_BLOCK (0x4)
该Command被使用来对OTP内的RSA Public Key栏位进行BLOCK的动作。BLOCK则表示SW无法读出OTP内的RSA Public Key。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x4 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x4
2.5.6. OTP_AES_KEY (0x5)
该Command被使用来存取OTP中的AES Key,总共包含16-Bytes的OTP位置。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x5 offset writedata
READ COMMAND:
otpctrl -r 0x5
Example:
制作AES KEY: echo '000102030405060708090A0B0C0D0E0F' | xxd -r -ps > aesKey.bin otpctrl -w 0x5 0x0 0x03020100 otpctrl -w 0x5 0x4 0x07060504 otpctrl -w 0x5 0x8 0x0B0A0908 otpctrl -w 0x5 0xC 0x0F0E0D0C
2.5.7. OTP_AES_KEY_LOCK (0x9)
该Command被使用来对OTP内的AES Key栏位进行LOCK的动作。LOCK表示无法更改OTP内的AES Key。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x9 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x9
2.5.8. OTP_AES_KEY_BLOCK (0xA)
该Command被使用来对OTP内的AES Key栏位进行BLOCK的动作。BLOCK则表示SW无法读出OTP内的AES Key。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0xA 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0xA
2.5.9. ERROR CODE
FF01: 无效的COMMAND
FF02: 无效的OTP地址
FF03: 无效的OTP执行许可证
2.6. OTP Command Support List for IC Muffin¶
2.6.1. OTP_RSA_N (0x0)
该Command被使用来存取OTP中的RSA Public N-Key,总共包含256-Bytes的OTP位置。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otp -w 0x0 offset writedata
READ COMMAND:
otpctrl -r 0x0
2.6.2. OTP_RSA_E (0x1)
该Command被使用来存取OTP中的RSA Public E-Key,总共包含4-Bytes的OTP位置。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x1 0x0 0x01000100
READ COMMAND:
otpctrl -r 0x1
2.6.3. OTP_SECURE_BOOT (0x2)
该Command被使用来启动secure boot,设置为0xFF表示启动secure boot。在设置完该Command后,须于下次启动才会生效。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x2 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x2
2.6.4. OTP_RSA_KEY_LOCK (0x3)
该Command被使用来对OTP内的RSA Public Key栏位进行LOCK的动作。LOCK表示无法更改OTP内的RSA Public Key。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x3 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x3
2.6.5. OTP_RSA_KEY_BLOCK (0x4)
该Command被使用来对OTP内的RSA Public Key栏位进行BLOCK的动作。BLOCK则表示SW无法读出OTP内的RSA Public Key。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x4 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x4
2.6.6. OTP_AES128_KEY (0x5~0xC)
该Command被使用来存取OTP中的AES Key,Muffin共有8把AES128 KEY,一把key占有16-Bytes的OTP位置。在设置完该Command后,须于下次启动才会生效。
ALL AESKEY WRITE COMMAND:
-
KEY1
WRITE COMMAND:
otpctrl -w 0x5 offset writedata
READ COMMAND:
otpctrl -r 0x5
Eample:
制作AES KEY: echo '000102030405060708090A0B0C0D0E0F' | xxd -r -ps > aesKey1.bin otpctrl -w 0x5 0x0 0x03020100 otpctrl -w 0x5 0x4 0x07060504 otpctrl -w 0x5 0x8 0x0B0A0908 otpctrl -w 0x5 0xC 0x0F0E0D0C
-
KEY2
WRITE COMMAND:
otpctrl -w 0x6 offset writedata
READ COMMAND:
otpctrl -r 0x6
Eample:
制作AES KEY: echo '00112233445566778899AABBCCDDEEFF' | xxd -r -ps > aesKey2.bin otpctrl -w 0x6 0x0 0x33221100 otpctrl -w 0x6 0x4 0x77665544 otpctrl -w 0x6 0x8 0xBBAA9988 otpctrl -w 0x6 0xC 0xFFEEDDCC
-
KEY3
WRITE COMMAND:
otpctrl -w 0x7 offset writedata
READ COMMAND:
otpctrl -r 0x7
Eample:
制作AES KEY: echo '030102030405060708090A0B0C0D0E0F' | xxd -r -ps > aesKey3.bin otpctrl -w 0x7 0x0 0x03020103 otpctrl -w 0x7 0x4 0x07060504 otpctrl -w 0x7 0x8 0x0B0A0908 otpctrl -w 0x7 0xC 0x0F0E0D0C
-
KEY4
WRITE COMMAND:
otpctrl -w 0x8 offset writedata
READ COMMAND:
otpctrl -r 0x8
Eample:
制作AES KEY: echo '04112233445566778899AABBCCDDEEFF' | xxd -r -ps > aesKey4.bin otpctrl -w 0x8 0x0 0x33221104 otpctrl -w 0x8 0x4 0x77665544 otpctrl -w 0x8 0x8 0xBBAA9988 otpctrl -w 0x8 0xC 0xFFEEDDCC
-
KEY5
WRITE COMMAND:
otpctrl -w 0x9 offset writedata
READ COMMAND:
otpctrl -r 0x9
Eample:
制作AES KEY: echo '050102030405060708090A0B0C0D0E0F' | xxd -r -ps > aesKey5.bin otpctrl -w 0x9 0x0 0x03020105 otpctrl -w 0x9 0x4 0x07060504 otpctrl -w 0x9 0x8 0x0B0A0908 otpctrl -w 0x9 0xC 0x0F0E0D0C
-
KEY6
WRITE COMMAND:
otpctrl -w 0xA offset writedata
READ COMMAND:
otpctrl -r 0xA
Eample:
制作AES KEY: echo '06112233445566778899AABBCCDDEEFF' | xxd -r -ps > aesKey6.bin otpctrl -w 0xA 0x0 0x33221106 otpctrl -w 0xA 0x4 0x77665544 otpctrl -w 0xA 0x8 0xBBAA9988 otpctrl -w 0xA 0xC 0xFFEEDDCC
-
KEY7
WRITE COMMAND:
otpctrl -w 0xB offset writedata
READ COMMAND:
otpctrl -r 0xB
Eample:
制作AES KEY: echo '070102030405060708090A0B0C0D0E0F' | xxd -r -ps > aesKey7.bin otpctrl -w 0xB 0x0 0x03020107 otpctrl -w 0xB 0x4 0x07060504 otpctrl -w 0xB 0x8 0x0B0A0908 otpctrl -w 0xB 0xC 0x0F0E0D0C
-
KEY8
WRITE COMMAND:
otpctrl -w 0xC offset writedata
READ COMMAND:
otpctrl -r 0xC
Eample:
制作AES KEY: echo '08112233445566778899AABBCCDDEEFF' | xxd -r -ps > aesKey8.bin otpctrl -w 0xC 0x0 0x33221108 otpctrl -w 0xC 0x4 0x77665544 otpctrl -w 0xC 0x8 0xBBAA9988 otpctrl -w 0xC 0xC 0xFFEEDDCC
2.6.7. OTP_AES128_KEY_LOCK (0xD,0xF,0x11,0x13,0x15,0x17,0x19,0x1B)
该Command被使用来对OTP内的AES Key栏位进行LOCK的动作。LOCK表示无法更改OTP内的AES Key。在设置完该Command后,须于下次启动才会生效。
-
LOCK AESkey1
WRITE COMMAND:
otpctrl -w 0xD 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0xD
-
LOCK AESkey2
WRITE COMMAND:
otpctrl -w 0xF 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0xF
-
LOCK AESkey3
WRITE COMMAND:
otpctrl -w 0x11 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x11
-
LOCK AESkey4
WRITE COMMAND:
otpctrl -w 0x13 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x13
-
LOCK AESkey5
WRITE COMMAND:
otpctrl -w 0x15 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x15
-
LOCK AESkey6
WRITE COMMAND:
otpctrl -w 0x17 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x17
-
LOCK AESkey7
WRITE COMMAND:
otpctrl -w 0x19 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x19
-
LOCK AESkey8
WRITE COMMAND:
otpctrl -w 0x1B 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x1B
2.6.8. OTP_AES128_KEY1_BLOCK (0xE,0x10,0x12,0x14,0x16,0x18,0x1A,0x1C)
该Command被使用来对OTP内的AES Key栏位进行BLOCK的动作。BLOCK则表示SW无法读出OTP内的AES Key。在设置完该Command后,须于下次启动才会生效。
-
BLOCK AESKEY1
WRITE COMMAND:
otpctrl -w 0xE 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0xE
-
BLOCK AESKEY2
WRITE COMMAND:
otpctrl -w 0x10 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x10
-
BLOCK AESKEY3
WRITE COMMAND:
otpctrl -w 0x12 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x12
-
BLOCK AESKEY4
WRITE COMMAND:
otpctrl -w 0x14 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x14
-
BLOCK AESKEY5
WRITE COMMAND:
otpctrl -w 0x16 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x16
-
BLOCK AESKEY6
WRITE COMMAND:
otpctrl -w 0x18 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x18
-
BLOCK AESKEY7
WRITE COMMAND:
otpctrl -w 0x1A 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x1A
-
BLOCK AESKEY8
WRITE COMMAND:
otpctrl -w 0x1C 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x1C
2.6.9. OTP_ROM_SEL_AESKEY (0x24)
该Command用来选择OTP中哪一把AESKey对IPL进行解密,该OTP的值不为0时,使能ROM code对IPL的解密。在设置完该Command后,须于下次启动才会生效。注:一旦写入此OTP,IPL必须使用CBC加密。
WRITE COMMAND:
otpctrl -w 0x24 offset writedata
READ COMMAND:
otpctrl -r 0x24
Example:
-
SEL AESKEY128_1
WRITE COMMAND:
otpctrl -w 0x24 0x0 0xFF000000
-
SEL AESKEY128_2
WRITE COMMAND:
otpctrl -w 0x24 0x0 0xFF0000FF
-
SEL AESKEY128_3
WRITE COMMAND:
otpctrl -w 0x24 0x0 0xFF00FF00
-
SEL AESKEY128_4
WRITE COMMAND:
otpctrl -w 0x24 0x0 0xFF00FFFF
-
SEL AESKEY128_5
WRITE COMMAND:
otpctrl -w 0x24 0x0 0xFFFF0000
-
SEL AESKEY128_6
WRITE COMMAND:
otpctrl -w 0x24 0x0 0xFFFF00FF
-
SEL AESKEY128_7
WRITE COMMAND:
otpctrl -w 0x24 0x0 0xFFFFFF00
-
SEL AESKEY128_8
WRITE COMMAND:
otpctrl -w 0x24 0x0 0xFFFFFFFF
另外IPL可以使用AES256解密,OTP中AESKEY256实际上是由OTP中两把AES128组合而成,组合和设置方式举例如下:
-
SEL AESKEY256_1
Composition mode: AES128key1 + AES128key2
WRITE COMMAND:
otpctrl -w 0x24 0x0 0x00FF0000
-
SEL AESKEY256_2
Composition mode: AES128key3 + AES128key4
WRITE COMMAND:
otpctrl -w 0x24 0x0 0x00FF00FF
-
SEL AESKEY256_3
Composition mode: AES128key5 + AES128key6
WRITE COMMAND:
otpctrl -w 0x24 0x0 0x00FFFF00
-
SEL AESKEY256_4
Composition mode: AES128key7 + AES128key8
WRITE COMMAND:
otpctrl -w 0x24 0x0 0x00FFFFFF
2.6.10. OTP_ROM_SEL_AESKEY_LOCK (0x25)
该Command被使用来对OTP内的OTP_ROM_SEL_AESKEY栏位进行LOCK的动作。LOCK表示无法更改OTP内的OTP_ROM_SEL_AESKEY。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x25 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x25
2.6.11. OTP_CUSTOMER_AREA (0xA0)
该区域一共有8K,开放给客户使用,以下是写OTP_CUSTOMER_AREA的cmd,需注意每次写4byte.offset最大为0x3fc。
WRITE COMMAND:
otpctrl -w 0xA0 offset writedata
READ COMMAND:
otpctrl -r 0xA0
Example:
WRITE COMMAND: otpctrl -w 0xA0 0x0 0x12345678 WRITE COMMAND: otpctrl -w 0xA0 0x4 0x09ABCDEF WRITE COMMAND: otpctrl -w 0xA0 0x8 0x33445566 最后4byte WRITE COMMAND: WRITE COMMAND: otpctrl -w 0xA0 0x3fC 0xAA778899
Uboot下可通过otpread cmd 读取customer area data,客户可模拟otpread process在uboot/kernel下读到customer area data。
2.6.12. OTP_CUSTOMER_AREA_LOCK(0xA1~0xA8)
该Command被使用来对OTP内的OTP_CUSTOMER_AREA栏位进行LOCK的动作。LOCK表示无法更改OTP内的OTP_CUSTOMER_AREA。在设置完该Command后,须于下次启动才会生效。
-
LOCK 0k~1K
WRITE COMMAND:
otpctrl -w 0xA1 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0xA1
-
LOCK 1k ~2K
WRITE COMMAND:
otpctrl -w 0xA2 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0xA2
-
LOCK 2k~3K
WRITE COMMAND:
otpctrl -w 0xA3 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0xA3
-
LOCK 3k~4K
WRITE COMMAND:
otpctrl -w 0xA4 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0xA4
-
LOCK 4k~5K
WRITE COMMAND:
otpctrl -w 0xA5 0x0 0xFFFFFFFF READ COMMAND: otpctrl -r 0xA5
-
LOCK 5k~6K
WRITE COMMAND:
otpctrl -w 0xA6 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0xA6
-
LOCK 6k~7K
WRITE COMMAND:
otpctrl -w 0xA7 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0xA7
-
LOCK 7k~8K
WRITE COMMAND:
otpctrl -w 0xA8 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0xA8
2.6.13. ERROR CODE
FF01: 无效的COMMAND
FF02: 无效的OTP地址
FF03: 无效的OTP执行许可证
2.7. OTP Command Support List for IC Mochi¶
注:Mochi IC 默认支持RSA4096签章验签
2.7.1. OTP_RSA_N (0x0)¶
该Command被使用来存取OTP中的RSA Public N-Key,总共包含512-Bytes的OTP位置。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otp -w 0x0 offset writedata
READ COMMAND:
otpctrl -r 0x0
2.7.2. OTP_RSA_E (0x1)¶
该Command被使用来存取OTP中的RSA Public E-Key,总共包含4-Bytes的OTP位置。在设置完该Command后,须于下次启动才会生效(此处与其他 IC 不一致)。
WRITE COMMAND:
otpctrl -w 0x1 0x0 0x00010001
READ COMMAND:
otpctrl -r 0x1
2.7.3. OTP_SECURE_BOOT (0x2)¶
该Command被使用来启动secure boot,设置为0xFF表示启动secure boot。在设置完该Command后,须于下次启动才会生效。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x2 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x2
2.7.4. OTP_RSA_KEY_LOCK (0x3)¶
与 Muffin 一致,请参看 IC Muffin。
2.7.5. OTP_RSA_KEY_BLOCK (0x4)¶
与 Muffin 一致,请参看 IC Muffin。
2.7.6. OTP_AES128_KEY (0x5~0xC)¶
与 Muffin 一致,请参看 IC Muffin。
2.7.7. OTP_AES128_KEY_LOCK (0xD,0xF,0x11,0x13,0x15,0x17,0x19,0x1B)¶
与 Muffin 一致,请参看 IC Muffin。
2.7.8. OTP_AES128_KEY1_BLOCK (0xE,0x10,0x12,0x14,0x16,0x18,0x1A,0x1C)¶
与 Muffin 一致,请参看 IC Muffin。
2.7.9. OTP_ROM_SEL_AESKEY (0x24)¶
与 Muffin 一致,请参看 IC Muffin。
2.7.10. OTP_ROM_SEL_AESKEY_LOCK (0x25)¶
与 Muffin 一致,请参看 IC Muffin。
2.7.11. OTP_CUSTOMER_AREA (0xA0)¶
与 Muffin 一致,请参看 IC Muffin。
2.7.12. ERROR CODE¶
FF01: 无效的COMMAND
FF02: 无效的OTP地址
FF03: 无效的OTP执行许可证
2.8. OTP Command Support List for IC Maruko¶
注:Maruko IC 支持 RSA2048 签章验签
2.8.1. OTP_RSA_N (0x0)
与 Muffin 一致,请参看 IC Muffin。
2.8.2. OTP_RSA_E (0x1)
与 Muffin 一致,请参看 IC Muffin。
2.8.3. OTP_SECURE_BOOT (0x2)
该Command被使用来启动secure boot,设置为0xFF表示启动secure boot。在设置完该Command后,须于下次启动才会生效。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x2 0x0 0xFF
READ COMMAND:
otpctrl -r 0x2
2.8.4. OTP_RSA_KEY_LOCK (0x3)
该Command被使用来对OTP内的RSA Public Key栏位进行LOCK的动作。LOCK表示无法更改OTP内的RSA Public Key。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x3 0x0 0xFF
READ COMMAND:
otpctrl -r 0x3
2.8.5. OTP_RSA_KEY_BLOCK (0x4)
该Command被使用来对OTP内的RSA Public Key栏位进行BLOCK的动作。BLOCK则表示SW无法读出OTP内的RSA Public Key。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x4 0x0 0xFF
READ COMMAND:
otpctrl -r 0x4
2.8.6. OTP_AES128_KEY (0x5~0xC)
该Command被使用来存取OTP中的AES Key,Maruko共有4把AES128 KEY,一把key占有16-Bytes的OTP位置。在设置完该Command后,须于下次启动才会生效。
ALL AESKEY WRITE COMMAND:
-
KEY1
WRITE COMMAND:
otpctrl -w 0x5 offset writedata
READ COMMAND:
otpctrl -r 0x5
Eample:
制作AES KEY: echo '000102030405060708090A0B0C0D0E0F' | xxd -r -ps > aesKey1.bin otpctrl -w 0x5 0x0 0x03020100 otpctrl -w 0x5 0x4 0x07060504 otpctrl -w 0x5 0x8 0x0B0A0908 otpctrl -w 0x5 0xC 0x0F0E0D0C
-
KEY2
WRITE COMMAND:
otpctrl -w 0x6 offset writedata
READ COMMAND:
otpctrl -r 0x6
Eample:
制作AES KEY: echo '00112233445566778899AABBCCDDEEFF' | xxd -r -ps > aesKey2.bin otpctrl -w 0x6 0x0 0x33221100 otpctrl -w 0x6 0x4 0x77665544 otpctrl -w 0x6 0x8 0xBBAA9988 otpctrl -w 0x6 0xC 0xFFEEDDCC
-
KEY3
WRITE COMMAND:
otpctrl -w 0x7 offset writedata
READ COMMAND:
otpctrl -r 0x7
Eample:
制作AES KEY: echo '030102030405060708090A0B0C0D0E0F' | xxd -r -ps > aesKey3.bin otpctrl -w 0x7 0x0 0x03020103 otpctrl -w 0x7 0x4 0x07060504 otpctrl -w 0x7 0x8 0x0B0A0908 otpctrl -w 0x7 0xC 0x0F0E0D0C
-
KEY4
WRITE COMMAND:
otpctrl -w 0x8 offset writedata
READ COMMAND:
otpctrl -r 0x8
Eample:
制作AES KEY: echo '04112233445566778899AABBCCDDEEFF' | xxd -r -ps > aesKey4.bin otpctrl -w 0x8 0x0 0x33221104 otpctrl -w 0x8 0x4 0x77665544 otpctrl -w 0x8 0x8 0xBBAA9988 otpctrl -w 0x8 0xC 0xFFEEDDCC
2.8.7. OTP_AES128_KEY_LOCK (0xD,0xF,0x11,0x13,0x15,0x17,0x19,0x1B)
该Command被使用来对OTP内的AES Key栏位进行LOCK的动作。LOCK表示无法更改OTP内的AES Key。在设置完该Command后,须于下次启动才会生效。
-
LOCK AESkey1
WRITE COMMAND:
otpctrl -w 0xD 0x0 0x01
READ COMMAND:
otpctrl -r 0xD
-
LOCK AESkey2
WRITE COMMAND:
otpctrl -w 0xF 0x0 0x04
READ COMMAND:
otpctrl -r 0xF
-
LOCK AESkey3
WRITE COMMAND:
otpctrl -w 0x11 0x0 0x10
READ COMMAND:
otpctrl -r 0x11
-
LOCK AESkey4
WRITE COMMAND:
otpctrl -w 0x13 0x0 0x40
READ COMMAND:
otpctrl -r 0x13
2.8.8. OTP_AES128_KEY1_BLOCK (0xE,0x10,0x12,0x14,0x16,0x18,0x1A,0x1C)
该Command被使用来对OTP内的AES Key栏位进行BLOCK的动作。BLOCK则表示SW无法读出OTP内的AES Key。在设置完该Command后,须于下次启动才会生效。
-
BLOCK AESKEY1
WRITE COMMAND:
otpctrl -w 0xE 0x0 0x02
READ COMMAND:
otpctrl -r 0xE
-
BLOCK AESKEY2
WRITE COMMAND:
otpctrl -w 0x10 0x0 0x08
READ COMMAND:
otpctrl -r 0x10
-
BLOCK AESKEY3
WRITE COMMAND:
otpctrl -w 0x12 0x0 0x20
READ COMMAND:
otpctrl -r 0x12
-
BLOCK AESKEY4
WRITE COMMAND:
otpctrl -w 0x14 0x0 0x80
READ COMMAND:
otpctrl -r 0x14
2.8.9. OTP_ROM_SEL_AESKEY (0x24)
该Command用来选择OTP中哪一把AESKey对IPL进行解密,该OTP的值不为0时,使能ROM code对IPL的解密。在设置完该Command后,须于下次启动才会生效。注:一旦写入此OTP,IPL必须使用CBC加密。
WRITE COMMAND:
otpctrl -w 0x24 offset writedata
READ COMMAND:
otpctrl -r 0x24
Example:
-
SEL AESKEY128_1
WRITE COMMAND:
otpctrl -w 0x24 0x0 0x80
-
SEL AESKEY128_2
WRITE COMMAND:
otpctrl -w 0x24 0x0 0x90
-
SEL AESKEY128_3
WRITE COMMAND:
otpctrl -w 0x24 0x0 0xA0
-
SEL AESKEY128_4
WRITE COMMAND:
otpctrl -w 0x24 0x0 0xB0
另外IPL可以使用AES256解密,OTP中AESKEY256实际上是由OTP中两把AES128组合而成,组合和设置方式如下:
-
SEL AESKEY256_1
Composition mode:
AES128key1 + AES128key2
WRITE COMMAND:
otpctrl -w 0x24 0x0 0x40
-
SEL AESKEY256_2
Composition mode:
AES128key3 + AES128key4
WRITE COMMAND:
otpctrl -w 0x24 0x0 0x50
2.8.10. OTP_ROM_SEL_AESKEY_LOCK (0x25)
该Command被使用来对OTP内的OTP_ROM_SEL_AESKEY栏位进行LOCK的动作。LOCK表示无法更改OTP内的OTP_ROM_SEL_AESKEY。在设置完该Command后,须于下次启动才会生效。
WRITE COMMAND:
otpctrl -w 0x25 0x0 0x08
READ COMMAND:
otpctrl -r 0x25
2.8.11. OTP_CUSTOMER_AREA (0xA0)
Maruko 无 Customer Area
2.8.12. ERROR CODE
FF01: 无效的COMMAND
FF02: 无效的OTP地址
FF03: 无效的OTP执行许可证
3. 安全镜像生成¶
3.1. 概述¶
此功能依据用户需求可分成是否进行明文内容的加密,如下两种制作流程,此流程能一路支持到Linux Kernel,如下章节会逐步介绍如何通过tool生成Images。
注意事项:
-
without AES
-
IPL.bin需先Insert CUST Key (Public Key),然后签章必须是由OTP KEY所生成
-
IPL_CUST.bin需先Insert CUST Key (Public Key),然后在通过CUST Key (Private Key) 生成签章,这边Insert的Key为用来验证IPL_CUST、U-Boot和Linux Kernel的签章
-
-
with AES
-
IPL.bin需先Insert CUST Key (Public Key),然后签章必须是由OTP KEY所生成
-
IPL_CUST.bin需先Insert CUST Key (Public Key),然后再通过CUST Key (Private Key) 生成签章,但不需要进行AES加密。这边Insert的CUST Key (Public Key)为用来验证U-Boot和Linux Kernel的签章。
-
U-Boot和Linux Kernel都需要先进行AES加密,然后再通过CUST Key (Private Key) 生成签章。
图3-1 签章流程
-
3.2. 制作RSA Key¶
这边的制作方式同样适用于OTP Key及CUST Key中的RSA Key,可依据客户需求使用同一把Key或制作出两把不同的RSA Key。出于安全性考虑,建议使用两把不同的RSA key。
请使用以下命令来生成Private.bin和Public.bin。
通过以下命令生成的E key值默认为0x10001,请勿自定义E key值。
3.2.1. RSA2048
-
生成RSA私钥
openssl genrsa -out private.pem 2048
-
生成RSA公钥
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
3.2.2. RSA4096
-
生成RSA私钥
openssl genrsa -out private.pem 4096
-
生成RSA公钥
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
3.3. 制作AES-128 Key¶
这边通过xxd tool来生成AES-128 key binary file
,请指定32bytes的key,通过如下command来生成。
echo '000102030405060708090A0B0C0D0E0F' | xxd -r -ps > aesKey.bin
3.4. USB签章¶
该操作仅在USB boot flow中需要使用
USB boot将会在USB upgrade场景下使用到,在该场景下,由ROM直接引导usb_updater.bin
启动,而usb_updater.bin
实则为IPL.bin append
至64K bytes得来。所以若此时开启securityboot,只需要对usb_updater.bin
中的IPL.bin
部分签章,再重新append至64K bytes即可,这边只需要一条command就可实现以上操作。
通过key_proc.py
执行:
./key_proc.py --signusb --rsa=./private-otp.pem -f usb_updater.bin
执行后会生成usb_updater.bin_append.sig.bin
,可用于烧录。
3.5. IPLX Separation¶
该操作仅在EMMC boot flow中需要使用
由于EMMC采用BOOT_PART.bin方案,所以只有IPL->U-Boot的storage方式是EMMC的时候才需要执行该步骤,SPI NOR、SPI NAND、SD等方式均不需要。BOOT_PART.bin包含IPLX和U-Boot,而IPLX又包含IPL和IPL_CUST, Sigmastar将release IPLX和U-Boot给customer,customer需自行使用如下命令从IPLX中分离出IPL和IPL_CUST,再分别进行签章。
通过key_proc.py执行:
./key_proc.py --split -f ./IPLX.bin
执行后会生成IPL.bin和IPL_CUST.bin
3.6. IPL.bin 签章¶
先将IPL Binary 重命名 为IPL.bin,IPL需要先Insert Key后再做签章。
IPL可进行AES加密,分为IPL加密和IPL不加密两种方案,IPL签章整个步骤如下:
IPL不加密:
-
Insert Key,通过key_proc.py执行:
./key_proc.py --insert --rsa=./public.pem -f ./IPL.bin
执行后会生成IPL.cipher.bin。
./add_ipl_header.py ./IPL.cipher.bin ./IPL.cipher2.bin 0 1(调试模式) ./add_ipl_header.py ./IPL.cipher.bin ./IPL.cipher2.bin 0 0(正式模式)
执行后会生成IPL.cipher2.bin。
-
制作签章,通过key_proc.py执行(注:必须用OTP的RSA Private Key签章)
./key_proc.py --sign --rsa=./private-otp.pem -f ./IPL.cipher2.bin
执行后会生成IPL.cipher2.sig.bin。
IPL加密(此方案 Pudding/Tiramisu 不支持):
-
Insert Key,通过key_proc.py执行:
./key_proc.py --insert --rsa=./public.pem --IV=IV.bin -f ./IPL.bin
执行后会生成IPL.cipher.bin。
./add_ipl_header.py ./IPL.cipher.bin ./IPL.cipher2.bin 0 1(调试模式) ./add_ipl_header.py ./IPL.cipher.bin ./IPL.cipher2.bin 0 0(正式模式)
执行后会生成IPL.cipher2.bin。
由于IPL使用CBC对Plain Text进行加密,故将使用到IV值。此功能需要烧写OTP_ROM_SEL_AESKEY(烧录方法见第二章),IV值可客户自定义,生成方式如下:
echo '00112233445566778899AABBCCDDEEFF' | xxd -r -ps > IV.bin
-
加密IPL,加密支持AESkey256,若使用AESkey256,需注意使用的aeskey.bin需是256bit:
./key_proc.py --encrypt --aes=./aeskey.bin -f ./IPL.cipher2.bin
执行后会生成IPL.cipher2.aes.bin。
-
制作签章,通过key_proc.py执行(注:必须用OTP的RSA Private Key签章)
./key_proc.py --sign --rsa=./private-otp.pem -f ./IPL.cipher2.aes.bin
执行后会生成IPL.cipher2.aes.sig.bin。
3.7. IPL_CUST.bin 签章¶
先将IPL_CUST Binary 重命名 为IPL_CUST.bin,IPL_CUST仅有一种方案,步骤如下:
IPL_CUST不加密:
-
Insert Key,通过key_proc.py执行:
./key_proc.py --insert --rsa=./public.pem -f ./IPL_CUST.bin
执行后会生成IPL_CUST.cipher.bin。
./add_ipl_header.py ./IPL_CUST.cipher.bin ./IPL_CUST.cipher2.bin 0 1(调试模式) ./add_ipl_header.py ./IPL_CUST.cipher.bin ./IPL_CUST.cipher2.bin 0 0(正式模式)
执行后会生成IPL_CUST.cipher2.bin。
-
制作签章,通过key_proc.py执行
./key_proc.py --sign --rsa=./private.pem -f ./IPL_CUST.cipher2.bin
执行后会生成IPL_CUST.cipher2.sig.bin。
3.8. U-Boot 签章¶
如下设定针对SPI NOR的U-Boot版本,其档名为u-boot.xz.img.bin
,如为SPI-NAND版本,请改u-boot_spinand.xz.img.bin
。Uboot有两种方案,分为UBOOT不加密和UBOOT加密。
-
UBOOT不加密
不需做Image的加密动作,执行后会产生u-boot.xz.img.sig.bin。
./key_proc.py --sign --rsa=./private.pem -f u-boot.xz.img.bin
-
UBOOT加密
需要先对Image做AES加密,执行后会产生u-boot.xz.img.aes.bin,之后再对加密后的Image进行签章,最后产生u-boot.xz.img.aes.sig.bin。
./key_proc.py --encrypt --aes=./aesKey.bin -f ./u-boot.xz.img.bin ./key_proc.py --sign --rsa=./private.pem -f ./u-boot.xz.img.aes.bin
3.9. BOOT_PART.bin Pack¶
该操作仅在EMMC boot flow中需要使用。
如 3.4. USB签章 介绍,BOOT_PART.bin
需要拆分为IPL、IPL_CUST和U-Boot单独签章,所以签章后需要再将三个image打包为新的BOOT_PART.bin
。且同样地,只有IPL → U-Boot的storage方式是EMMC的时候才需要执行该步骤,SPI NOR、SPI NAND、SD等方式均不需要。
通过cat执行即可:
cat IPL.cipher2.sig.bin IPL_CUST.cipher2.sig.bin > IPLX.bin cat IPLX.bin u-boot.xz.img.sig.bin > BOOT_PART.bin
3.10. Linux Kernel 签章¶
KERNEL有两种方案,分为KERNEL不加密和KERNEL加密。
-
Kernel不加密方案
不需做Image的加密动作,执行后会生成kernel.sig.bin。
./key_proc.py --sign --rsa=./private.pem -f kernel.bin
-
Kernel加密方案
需要先对Image做AES加密,执行后会生成kernel.aes.bin,之后再对加密后的Image进行签章,最后生成kernel.aes.sig.bin。
./key_proc.py --encrypt --aes=./aesKey.bin -f ./kernel.bin ./key_proc.py --sign --rsa=./private.pem -f ./kernel.aes.bin
3.11. Linux Rootfs 签章¶
-
Rootfs不加密
不需做Image的加密动作,执行后会生成rootfs.sig.sqfs
./key_proc.py --sign --rsa=./private.pem -f rootfs.sqfs
-
Rootfs加密
非ramdisk属性的rootfs无法支持加解密机制
3.12. 签章验证¶
-
将完成签章的Images刻录至flash中,刻录后如能正常进入U-Boot,表示从IPL至U-Boot的签章是没有问题的。
-
在Uboot阶段需要设定环境变量来对Linux Kernel进行验证,其原理是通过sigauth命令来对Binary进行验签和解密,如下:
-
验签
sigauth <Binary_Addr> <KEY_Addr>
-
验签+解密
sigauth <Binary_Addr> <KEY_Addr> --aes
请参考如下command进行设定:
-
非onebin方案
-
不包含AES加密的Kernel验签
SPI-NOR:
setenv bootcmd 'sf probe 0;sf read 0x22000000 ${sf_kernel_start} ${sf_kernel_size}; mxp r.info IPL_CUST; sf read 0x23C00000 ${sf_part_start} ${sf_part_size}; dcache off; sigauth 0x22000000 0x23C00000; dcache on; bootm 0x22000000'; saveenv;
SPI-NAND:
setenv bootcmd 'nand read.e 0x23C00000 IPL_CUST0 0x20000; nand read.e 0x22000000 KERNEL 0x500000; dcache off; sigauth 0x22000000 0x23C00000; dcache on; bootm 0x22000000'; saveenv;
EMMC:
setenv bootcmd 'emmc read.p 0x22000000 kernela 0x300000; mmc dev 0 1; mmc read 0x21000000 0 0x200; emmc_get_cust 0x21000000; mmc partconf 0 1 1 0; dcache off; sigauth 0x22000000 $(cust_address); dcache on; bootm 0x22000000'; saveenv;
注意:以上command默认从EMMC0启动,若从EMMC1启动,则
mmc dev 0 1
需改为mmc dev 1 1
。SD + SPI-NOR:
setenv bootcmd 'fatload mmc 0:1 0x21000000 IPL_CUST 0; sf probe 0; mxp r.info KERNEL; sf read 0x22000000 ${sf_part_start} ${sf_part_size}; dcache off; sigauth 0x22000000 0x23C00000; dcache on; bootm 0x22000000'; saveenv;
注意:以上command默认从SD0启动,若从SD1启动,则
fatload mmc 0:1
需改为fatload mmc 1:1
。SD + SPI-NAND:
setenv bootcmd 'fatload mmc 0:1 0x23C00000 IPL_CUST 0; nand read.e 0x22000000 KERNEL; dcache off; sigauth 0x22000000 0x23C00000; dcache on; bootm 0x22000000'; saveenv;
注意:以上command默认从SD0启动,若从SD1启动,则
fatload mmc 0:1
需改为fatload mmc 1:1
。 -
包含AES加密
请在对应的启动方式上的sigauth命令的尾部加上 --aes。如:
dcache off; sigauth 0x22000000 0x23C00000 --aes; dcache on;
-
-
onebin方案
-
不包含AES加密的Kernel验签
SPI-NOR:
setenv bootcmd 'sf probe 0; sf read 0x22000000 KERNEL ${kernel_file_size}; dcache off; sigauth 0x22000000 0x23C00000; dcache on; bootm 0x22000000'; saveenv;
SPI-NAND:
setenv bootcmd 'nand read.e 0x22000000 KERNEL 0x500000; dcache off; sigauth 0x22000000 0x23C00000; dcache on; bootm 0x22000000'; saveenv;
EMMC:
-
Kernel验签 (For Uboot2021 Support)
setenv bootcmd ' dcache off; sigauth 0x22000000 0x21000000; dcache on; bootm 0x22000000'; saveenv;
-
Kernel验签 (For Uboot2015 Support)
setenv bootcmd 'emmc read.p 0x22000000 kernel 0x300000; mmc dev 0 1; mmc read 0x21000000 0 0x200; emmc_get_cust 0x21000000; mmc partconf 0 1 1 0; dcache off; sigauth 0x22000000 $(cust_address); dcache on; bootm 0x22000000'; saveenv;
注意: 以上command默认从EMMC0启动,若从EMMC1启动,则
mmc dev 0 1
需改为mmc dev 1 1
。 -
-
包含AES加密
请在对应的启动方式上的sigauth命令的尾部加上 --aes。如:
dcache off; sigauth 0x22000000 0x23C00000 --aes; dcache on;
-
-
-
若customer有验签rootfs的需求,在Uboot阶段需要设定环境变量来对Linux Rootfs进行验证,请参考如下command进行设定:
-
非onebin方案
-
不包含AES加密
SPI-NOR:
setenv rootfs_size [size] 结合kernel验签的bootcmd 如实际烧录的rootfs size为0x1af100,则 setenv rootfs_size 1af100; saveenv;
Kernel验签+ rootfs验签: setenv bootcmd 'dcache off; sf probe 0; mxp r.info rootfs; sf read 0x22000000 ${sf_part_start} ${sf_part_size}; mxp r.info IPL_CUST; sf read 0x23C00000 ${sf_part_start} ${sf_part_size}; sigauth 0x22000000 0x23C00000; sf read 0x22000000 ${sf_kernel_start} ${sf_kernel_size}; sigauth 0x22000000 0x23C00000; dcache on; bootm 0x22000000'; saveenv;
rootfs验签命令为: sf probe 0; mxp r.info rootfs; sf read 0x22000000 ${sf_part_start} ${sf_part_size}; mxp r.info IPL_CUST; sf read 0x23C00000 ${sf_part_start} ${sf_part_size}; dcache off; sigauth 0x22000000 0x23C00000; dcache on;
Kernel(验签+解密)+ rootfs验签: setenv bootcmd 'dcache off; sf probe 0; mxp r.info rootfs; sf read 0x22000000 ${sf_part_start} ${sf_part_size}; mxp r.info IPL_CUST; sf read 0x23C00000 ${sf_part_start} ${sf_part_size}; sigauth 0x22000000 0x23C00000; sf read 0x22000000 ${sf_kernel_start} ${sf_kernel_size}; sigauth 0x22000000 0x23C00000 --aes; dcache on; bootm 0x22000000'; saveenv;
SPI-NAND:
setenv rootfs_size [size] 结合kernel验签的bootcmd 如实际烧录的rootfs size为0x1af100,则 setenv rootfs_size 1af100; saveenv;
Kernel验签+ rootfs验签: setenv bootcmd 'dcache off; nand read.e 0x23C00000 IPL_CUST0 0x20000; nand read.e 0x22000000 rootfs 0x600000; sigauth 0x22000000 0x23C00000; nand read.e 0x22000000 KERNEL 0x500000; sigauth 0x22000000 0x23C00000; dcache on; bootm 0x22000000'; saveenv;
rootfs验签命令为: nand read.e 0x23C00000 IPL_CUST0 0x20000;nand read.e 0x22000000 rootfs 0x600000; dcache off; sigauth 0x22000000 0x23C00000; dcache on;
Kernel(验签+解密)+ rootfs验签: setenv bootcmd 'dcache off; nand read.e 0x23C00000 IPL_CUST0 0x20000; nand read.e 0x22000000 rootfs 0x600000; sigauth 0x22000000 0x23C00000; nand read.e 0x22000000 KERNEL 0x500000; sigauth 0x22000000 0x23C00000 --aes; dcache on; bootm 0x22000000'; saveenv;
SD + SPI-NOR:
setenv rootfs_size [size] 结合kernel验签的bootcmd 如实际烧录的rootfs size为0x1af100,则 setenv rootfs_size 1af100; saveenv;
Kernel验签+ rootfs验签: setenv bootcmd ' dcache off; fatload mmc 0:1 0x21000000 IPL_CUST 0; sf probe 0; mxp r.info rootfs; sf read 0x22000000 ${sf_part_start} ${sf_part_size}; sigauth 0x22000000 0x23C00000; fatload mmc 0:1 0x21000000 IPL_CUST 0; sf probe 0; mxp r.info KERNEL; sf read 0x22000000 ${sf_part_start} ${sf_part_size}; sigauth 0x22000000 0x23C00000; dcache on; bootm 0x22000000; saveenv;
rootfs验签命令为: fatload mmc 0:1 0x21000000 IPL_CUST 0; sf probe 0; mxp r.info rootfs; sf read 0x22000000 ${sf_part_start} ${sf_part_size}; dcache off; sigauth 0x22000000 0x23C00000; dcache on;
Kernel(验签+解密)+ rootfs验签: setenv bootcmd ' dcache off; atload mmc 0:1 0x21000000 IPL_CUST 0; sf probe 0; mxp r.info rootfs; sf read 0x22000000 ${sf_part_start} ${sf_part_size}; sigauth 0x22000000 0x23C00000; fatload mmc 0:1 0x21000000 IPL_CUST 0; sf probe 0; mxp r.info KERNEL; sf read 0x22000000 ${sf_part_start} ${sf_part_size}; sigauth 0x22000000 0x23C00000 --aes; dcache on; bootm 0x22000000; saveenv;
注意:以上command默认从SD0启动,若从SD1启动,则
fatload mmc 0:1
需改为fatload mmc 1:1
。SD + SPI-NAND:
setenv rootfs_size [size] 结合kernel验签的bootcmd 如实际烧录的rootfs size为0x1400100,则 setenv rootfs_size 1400100; saveenv;
Kernel验签+ rootfs验签: setenv bootcmd ' dcache off; fatload mmc 0:1 0x23C00000 IPL_CUST 0; nand read.e 0x22000000 rootfs 0x600000; sigauth 0x22000000 0x23C00000; fatload mmc 0:1 0x23C00000 IPL_CUST 0; nand read.e 0x22000000 KERNEL; sigauth 0x22000000 0x23C00000; dcache on; bootm 0x22000000'; saveenv;
rootfs验签命令为: fatload mmc 0:1 0x23C00000 IPL_CUST 0; nand read.e 0x22000000 rootfs 0x600000; dcache off; sigauth 0x22000000 0x23C00000; dcache on;
Kernel(验签+解密)+ rootfs验签: setenv bootcmd ' dcache off; fatload mmc 0:1 0x23C00000 IPL_CUST 0; nand read.e 0x22000000 rootfs 0x600000; sigauth 0x22000000 0x23C00000; fatload mmc 0:1 0x23C00000 IPL_CUST 0; nand read.e 0x22000000 KERNEL; sigauth 0x22000000 0x23C00000 --aes; dcache on; bootm 0x22000000'; saveenv;
注意:以上command默认从SD0启动,若从SD1启动,则
fatload mmc 0:1
需改为fatload mmc 1:1
。 -
包含AES加密: 非ramdisk属性的rootfs无法支持加解密机制。
-
-
onebin方案
-
不包含AES加密
SPI-NOR:
setenv rootfs_size [size] 结合kernel验签的bootcmd 如实际烧录的rootfs size为0x1af100,则 setenv rootfs_size 1af100; saveenv;
Kernel验签+ rootfs验签: setenv bootcmd 'dcache off; sf probe 0; sf read 0x22000000 ROOFS ${ rootfs_size }; sigauth 0x22000000 0x23C00000; sf read 0x22000000 KERNEL ${kernel_file_size}; sigauth 0x22000000 0x23C00000; dcache on; bootm 0x22000000'; saveenv;
rootfs验签命令为: sf probe 0; mxp r.info rootfs; sf read 0x22000000 KERNEL ${kernel_file_size};dcache off; sigauth 0x22000000 0x23C00000; dcache on;
Kernel(验签+解密)+ rootfs验签: setenv bootcmd 'dcache off; sf probe 0; sf read 0x22000000 ROOFS ${ rootfs_size }; sigauth 0x22000000 0x23C00000; sf read 0x22000000 KERNEL ${kernel_file_size}; sigauth 0x22000000 0x23C00000 --aes; dcache on; bootm 0x22000000'; saveenv;
SPI-NAND:
setenv rootfs_size [size] 结合kernel验签的bootcmd 如实际烧录的rootfs size为0x1af100,则 setenv rootfs_size 1af100; saveenv;
Kernel验签+ rootfs验签: setenv bootcmd 'dcache off; nand read.e 0x22000000 rootfs 0x600000; sigauth 0x22000000 0x23C00000; nand read.e 0x22000000 KERNEL 0x500000; sigauth 0x22000000 0x23C00000; dcache on; bootm 0x22000000'; saveenv;
rootfs验签命令为: nand read.e 0x22000000 rootfs 0x600000; dcache off; sigauth 0x22000000 0x23C00000; dcache on;
Kernel(验签+解密)+ rootfs验签: setenv bootcmd 'dcache off;nand read.e 0x22000000 rootfs 0x600000; sigauth 0x22000000 0x23C00000; nand read.e 0x22000000 KERNEL 0x500000; sigauth 0x22000000 0x23C00000 --aes; dcache on; bootm 0x22000000'; saveenv;
-
-
4. 注意事项¶
4.1. IPL¶
针对Secure Boot的功能,特定的IPL及IPL_CUST必须被使用。
4.1.1. 普通安全boot流程
-
IPL
IPL.bin
-
IPL_CUST
IPL_CUST.bin
4.1.2. 加密安全boot流程
-
IPL
IPL.AES.bin
-
IPL_CUST
IPL_CUST.AES.bin
4.2. 自编tool签章¶
-
Pudding IC & Tiramisu IC
针对U-Boot、Linux Kernel来生成签章文件时,仅使用其的Data部分来进行SHA计算,并通过RSA来产生256Bytes的签章,所以如客户为使用自行编制的tool来产生签章,须注意 应排除U-Boot和Linux Kernel前64Bytes的Header ,仅以Data部分来进行计算。
-
Muffin IC & Mochi IC & Maruko IC
针对U-Boot、Linux Kernel来生成签章文件时,将使用HEADER+Data部分来进行SHA计算,并通过RSA来产生256Bytes的签章,所以如客户为使用自行编制的tool来产生签章,须注意 应包含U-Boot和Linux Kernel的 Header ,以HEADER+Data部分来进行计算。
注:Muffin IC uboot header为 64byte,kernel header为 80byte
-
ALL Chip
AES加密都不包含Header,仅将Data部分来进行加密。
4.3. EMMC BOOT_PART.bin签章¶
必须单独对IPL、IPL_CUST、U-Boot进行签章,签章后再重新打包为新的BOOT_PART.bin烧入(见3.5. IPLX Separation和3.9. BOOT_PART.bin Pack)
5. SECURITYBOOT部署流程¶
5.1. SecurityBoot调试流程¶
若确认需要使用OTP烧录来串通SecurityBoot flow,则调试阶段务必按照以下flow,即先烧录部分OTP进行测试,否则可能由于错误的操作导致系统无法启动甚至IC作废,待调试PASS以后再考虑一次性烧录所有OTP
5.1.1. 烧录OTP(KEY)
使用U-Boot Command或Linux Tool烧录RSA Public NKey/Ekey(或AES Key)。
注意: U-Boot Command烧录方法详见第2章 OTP Key读写操作说明,Linux Tool烧录方式请跟FAE确认。
5.1.2. 签章image
对IPL/IPL_CUST/U-Boot进行签章(或加密)并烧入flash。
其中IPL/IPL_CUST务必用调试流程的签章方法(目的是代替OTP中的SecurityBoot enable bit来开启SecurityBoot flow)。
注意: 调试流程的签章方法见3.6. IPL.bin 签章和3.7. IPL_CUST.bin 签章
5.1.3. 检验验签(或解密)结果
首先需要确认ROM->IPL->IPL_CUST->U-Boot已进行到SecurityBoot的flow。
-
ROM->IPL确认是否走SecurityBoot的方式
ROM验签IPL成功不会有任何log,但验签失败则会打印AUTH ERR(波特率可能需要调为38400或57600,否则乱码),所以可以烧入未签章的IPL到flash,若ROM->IPL已进行到SecurityBoot的flow,则会报AUTH ERR。
-
IPL->IPL_CUST->U-Boot确认是否走SecurityBoot的方式
查看log即可,一般带有KEYN_ADDRESS或secure boot关键字,若开启解密流程则还会有KEYAES_ADDRESS关键字。
举例如下:
确认后,需确保能启动到U-Boot才能继续下一步烧录。
5.1.4. 烧录OTP(ENABLE)
使用U-Boot Command或Linux Tool烧录SecurityBoot enable bit。
注意: U-Boot Command烧录方法详见第2章 OTP Key读写操作说明,Linux Tool烧录方式请跟FAE确认。
烧录后按照上述方法确认ROM->IPL->IPL_CUST->U-Boot有走到SecurityBoot并能启动到U-Boot,然后继续下一步烧录。
5.1.5. 烧录OTP(LOCK)
使用U-Boot Command或Linux Tool烧录RSA KEY的LOCK和BLOCK。
注意: U-Boot Command烧录方法详见第2章 OTP Key读写操作说明,Linux Tool烧录方式请跟FAE确认。
烧录后同样按照5.1.3的方法确认ROM->IPL->IPL_CUST->U-Boot有走到SecurityBoot并能启动到U-Boot,到此ROM->IPL->IPL_CUST->U-Boot的SecurityBoot flow和OTP相关验证已经PASS。
接下来根据3.12. 签章验证的方法验证U-Boot以后的SecurityBoot flow。
5.2. SecurityBoot正式流程(普通流程,Only RSA)¶
为了防止误操作导致系统无法启动甚至IC作废,调试流程PASS以后,才能进行正式流程。
5.2.1. 签章image(ALL)
使用python script将所有需要验签的image都执行一遍签章,再烧入flash,其中IPL/IPL_CUST可以使用正式模式的签章方法(因为OTP中的SecurityBoot enable bit会被烧录,不需要用software来模拟了)
注意: 正式模式的签章方法见3.6. IPL.bin 签章和3.7. IPL_CUST.bin 签章。
5.2.2. 烧录OTP(ALL)
使用U-Boot Command或Linux Tool烧录所有OTP case。
注意: U-Boot Command烧录方法详见第2章 OTP Key读写操作说明,Linux Tool烧录方式请跟FAE确认。
5.3. SecurityBoot正式流程(加密流程,RSA+AES)¶
5.3.1. 参考理论设计方案一
为了防止误操作导致系统无法启动甚至IC作废,调试流程PASS以后,才能进行正式流程。
-
签章image(ALL)
使用python script对image只执行签章(或不签章,若只进行签章则需用特定的IPL/IPL_CUST),烧入flash,再使用python script对image执行签章和加密,用于网络或USB等方式升级。
注意:签章方法见第3章,其中IPL/IPL_CUST可以使用 正式模式 的签章方法(因为OTP中的SecurityBoot enable bit会被烧录,不需要用software来模拟了), 正式模式 的签章方法签章方法见3.6. IPL.bin 签章和3.7. IPL_CUST.bin 签章。
-
烧录OTP(ALL)
使用U-Boot Command或Linux Tool烧录所有OTP case。
注意: U-Boot Command烧录方法详见第2章 OTP Key读写操作说明,Linux Tool烧录方式请跟FAE确认。
-
Upgrade
若分区中image未签章,则OTP烧录后,不能重启,应立即通过网络或USB upgrade加密image。
若分区中image有签章,则OTP烧录后,可以重启,但仍需通过网络或USB upgrade加密image。
5.3.2. 参考理论设计方案二
为了防止误操作导致系统无法启动甚至IC作废,调试流程PASS以后,才能进行正式流程。
-
签章和加密image(ALL)
划分两套分区,使用python script对image只执行签章(或不签章,若只进行签章则需用特定的IPL/IPL_CUST),烧入第一套分区,再使用python script对image执行签章和加密,烧入第二套分区。
注意: 签章方法见第3章,其中IPL/IPL_CUST可以使用 正式模式 的签章方法(因为OTP中的SecurityBoot enable bit会被烧录,不需要用software来模拟了), 正式模式 的签章方法签章方法见3.6. IPL.bin 签章和3.7. IPL_CUST.bin 签章。
-
烧录OTP(ALL)
从第一套分区启动,使用U-Boot Command或Linux Tool烧录所有OTP case。
注意: U-Boot Command烧录方法详见第2章 OTP Key读写操作说明,Linux Tool烧录方式请跟FAE确认。
-
Upgrade
若第一套分区未签章,则OTP烧录后,不能重启,应立即将第二套分区内容upgrade到第一套分区中。
若第一套分区有签章,则OTP烧录后,可以重启,但仍需将第二套分区内容upgrade到第一套分区中。
6. ANti_rollback¶
6.1. 概述¶
防回滚机制,其目的是为了防止IPL/IPL_CUST/UBOOT/KERNEL/RTOS降级到以前的版本,通过OTP中的Version Ctrl与IPL/IPL_CUST/UBOOT/KERNEL/RTOS Header Version进行对比,如果Header Version >= OTP Version 则booting,Header Version < OTP Version 则halt,以此来保证IPL/IPL_CUST/UBOOT/KERNEL/RTOS的版本为最新。
其中IPL的Header Version 默认为2Bit Or 1Bit操作,无法修改。IPL_CUST/UBOOT/KERNEL/RTOS 默认为2Bit Or 1Bit操作,可修改。
以下文档均为2Bit Or 1Bit下的说明。
注:Header Version为当前的版本号, OTP Version则需要数OTP栏位中有多少个1,再与Header Version进行对比。
6.2. Enable AntiRollback¶
通过烧录OTP中的OTP_ROM_ANTI_ROLLBACK的栏位来启动整个AntiRollback功能,一旦启动AntiRollback后,在ROM阶段就会开始进行IPL的版本校验。启动方式可通过烧录OTP_ENABLE_ANTI_ROLLBACK (0x12)。重启后生效。
WRITE COMMAND:
otpctrl -w 0x12 0x0 0x80
READ COMMAND:
otpctrl -r 0x12
6.3. IPL进版次数¶
6.3.1. OTP Version Ctrl
IPL的OTP版本号有64次进版次数。
可在UBOOT下通过以下cmd来修改读取IPL OTP Version。
WRITE COMMAND:
otpctrl -w 0x13 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x13
需要注意IPL OTP Version为 2Bit OR 1Bit 操作,若要写1,需要将两个bit同时置1,举例:
-
IPL OTP Version = 1
WRITE COMMAND:
otpctrl -w 0x13 0x0 0x00000003
-
IPL OTP Version = 2
WRITE COMMAND:
otpctrl -w 0x13 0x0 0x0000000F
-
IPL OTP Version = 8
WRITE COMMAND:
otpctrl -w 0x13 0x0 0x0000FFFF
-
IPL OTP Version = 64
WRITE COMMAND:
otpctrl -w 0x13 0x0 0xFFFFFFFF otpctrl -w 0x13 0x1 0xFFFFFFFF otpctrl -w 0x13 0x2 0xFFFFFFFF otpctrl -w 0x13 0x3 0xFFFFFFFF
6.3.2. IPL Header Version
-
Make
编译IPL时,需要带上ANTI=XX, XX为十六进制数,并且会将XX插入在IPL Header中。IPL与IPL_CUST共用ANTI参数。
例如,IPL_CUST Header Version 为12:
make ANTI=C
-
add_ipl_header.py
用法:./add_ipl_header.py [CID] [AUTH] [ANTI]
通过脚本修改IPL_CUST Header Version 为12:
./add_ipl_header.py ./IPL_CUST.bin ./IPL_CUST2.bin 0 0 C
6.4. IPL_CUST进版次数¶
6.4.1. OTP Version Ctrl
IPL_CUST的OTP版本号有16次进版次数。
可在UBOOT下通过以下cmd来修改读取IPL_CUST OTP Version。
WRITE COMMAND:
otpctrl -w 0x14 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x14
需要注意IPL_CUST OTP Version为 2Bit OR 1Bit 操作,若要写1,需要将两个bit同时置1,举例:
-
IPL_CUST OTP Version = 1
WRITE COMMAND:
otpctrl -w 0x14 0x0 0x00000003
-
IPL_CUST OTP Version = 2
WRITE COMMAND:
otpctrl -w 0x14 0x0 0x0000000F
-
IPL_CUST OTP Version = 8
WRITE COMMAND:
otpctrl -w 0x14 0x0 0x0000FFFF
6.4.2. IPL_CUST Header Version
-
Make
编译IPL时,需要带上ANTI=XX, XX为十六进制数,并且会将XX插入在IPL_CUST Header中。IPL与IPL_CUST共用ANTI参数。
例如,IPL_CUST Header Version 为12:
make ANTI=C
-
add_ipl_header.py
用法:./add_ipl_header.py [CID] [AUTH] [ANTI]
通过脚本修改IPL_CUST Header Version 为12:
./add_ipl_header.py ./IPL_CUST.bin ./IPL_CUST2.bin 0 0 C
6.5. UBOOT进版次数¶
6.5.1. OTP Version Ctrl
UBOOT的OTP版本号有16次进版次数。
可在UBOOT下通过以下cmd来修改读取UBOOT OTP Version。
WRITE COMMAND:
otpctrl -w 0x15 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x15
需要注意UBOOT OTP Version为 2Bit OR 1Bit 操作,若要写1,需要将两个bit同时置1,举例:
-
UBOOT OTP Version = 1
WRITE COMMAND:
otpctrl -w 0x15 0x0 0x00000003
-
UBOOT OTP Version = 2
WRITE COMMAND:
otpctrl -w 0x15 0x0 0x0000000F
-
UBOOT OTP Version = 8
WRITE COMMAND:
otpctrl -w 0x15 0x0 0x0000FFFF
6.5.2. UBOOT Header Version
修改UBOOT的Header Version时,需要手动修改根目录下的Makefile,如下:
由于ANTI是通过---lib_type带入Header,所以在UBOOT Header中ANTI的值以ASCII码的十六进制格式存储。
ANTI的数值在UBOOT Header中占两个byte。
Makefile中的ANTI必须以十进制数格式存在且不可舍弃十位数上的0,在—libtype时会将数值转成对应的字符,这样可保证其对应的十六进制在0x30-0x39间。
举例:
-
设定UBOOT Header Version 为5时,修改UBOOT根目录下的Makefile
ANTI=05
-
设定UBOOT Header Version 为12时,修改UBOOT根目录下的Makefile
ANTI=12 [(ANTI=0C)是错误的写法!!!]
6.6. KERNEL进版次数¶
6.6.1. OTP Version Ctrl
KERNEL的OTP版本号有40次进版次数。
可在UBOOT下通过以下cmd来修改读取KERNEL OTP Version。
WRITE COMMAND:
otpctrl -w 0x16 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x16
需要注意KERNEL OTP Version为 2Bit OR 1Bit 操作,若要写1,需要将两个bit同时置1,举例:
-
KERNEL OTP Version = 1
WRITE COMMAND:
otpctrl -w 0x16 0x0 0x00000003
-
KERNEL OTP Version = 2
WRITE COMMAND:
otpctrl -w 0x16 0x0 0x0000000F
-
KERNEL OTP Version = 8
WRITE COMMAND:
otpctrl -w 0x16 0x0 0x0000FFFF
6.6.2. KERNEL Header Version
修改KERNEL的Header Version时,需要手动修改根目录下的Makefile,如下:
由于ANTI是通过---lib_type带入Header,所以在KERNEL Header中ANTI的值以ASCII码的十六进制格式存储。
ANTI的数值在UBOOT Header中占两个byte。
Makefile中的ANTI必须以十进制数格式存在且不可舍弃十位数上的0,在—libtype时会将数值转成对应的字符,这样可保证其对应的十六进制在0x30-0x39间。
举例:
-
设定KERNEL Header Version 为5时,修改KERNEL根目录下的Makefile
ANTI=05
-
设定KERNEL Header Version 为12时,修改KERNEL根目录下的Makefile
ANTI=12 [(ANTI=0C)是错误的写法!!!]
6.7. RTOS进版次数¶
6.7.1. OTP Version Ctrl
RTOS的OTP版本号有24次进版次数。
可在UBOOT下通过以下cmd来修改读取RTOS OTP Version。
WRITE COMMAND:
otpctrl -w 0x17 0x0 0xFFFFFFFF
READ COMMAND:
otpctrl -r 0x17
需要注意RTOS OTP Version为 2Bit OR 1Bit 操作,若要写1,需要将两个bit同时置1,举例:
-
RTOS OTP Version = 1
WRITE COMMAND:
otpctrl -w 0x17 0x0 0x00000003
-
RTOS OTP Version = 2
WRITE COMMAND:
otpctrl -w 0x17 0x0 0x0000000F
-
RTOS OTP Version = 8
WRITE COMMAND:
otpctrl -w 0x17 0x0 0x0000FFFF
6.7.2. RTOS Header Version
修改RTOS的Header Version时,需要手动修改proj/tng/link.mak,如下:
ANTI是通过python写入Header,ANTI的数值在RTOS Header中占一个byte。
Link.mak中的ANTI必须以十进制数格式存在。
举例:
-
设定RTOS Header Version 为5时,修改RTOS目录下的proj/tng/link.mak
ANTI=05
-
设定RTOS Header Version 为12时,修改RTOS目录下的proj/tng/link.mak
ANTI=12 [ (ANTI=0C) 是错误的写法!!!]