1 /*
2 * Copyright (C) 2023 Rockchip Electronics Co., Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <string.h>
18 #include <stdlib.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <errno.h>
24 #include <stdbool.h>
25 #include "rkimage.h"
26 #include "log.h"
27 #include "rktools.h"
28 #include "crc.h"
29 #include "../mtdutils/mtdutils.h"
30
31
32 USHORT m_usFlashDataSec;
33 USHORT m_usFlashBootSec;
34 DWORD m_dwLoaderSize;
35 DWORD m_dwLoaderDataSize;
36 DWORD uiSecNumPerIDB;
37 size_t uiFlashPageSize;
38 size_t uiFlashBlockSize;
39 USHORT usPhyBlokcPerIDB;
40 bool m_bRc4Disable;
41 DWORD m_idBlockOffset[IDB_BLOCKS];
42
43 long long m_FlashSize;
44 long long m_FlasBlockNum;
45 PSTRUCT_RKBOOT_HEAD pBootHead;
46
47
CheckUid(BYTE uidSize,BYTE * pUid)48 static bool CheckUid(BYTE uidSize, BYTE *pUid)
49 {
50 if (uidSize != RKDEVICE_UID_LEN) {
51 return false;
52 }
53 USHORT oldCrc, newCrc;
54 oldCrc = *(USHORT *)(pUid + RKDEVICE_UID_LEN - 2);
55 newCrc = CRC_CCITT(pUid, RKDEVICE_UID_LEN - 2);
56 if (oldCrc != newCrc) {
57 return false;
58 }
59 return true;
60 }
61
UshortToBCD(USHORT num)62 static USHORT UshortToBCD(USHORT num)
63 {
64 USHORT bcd = 0;
65 bcd = (num % 10) | ( ((num / 10 ) % 10) << 4 ) | ( ((num / 100) % 10) << 8) | ( ((num / 1000) % 10) << 12);
66 return bcd;
67 }
ByteToBCD(BYTE num)68 static BYTE ByteToBCD(BYTE num)
69 {
70 BYTE bcd = 0;
71 bcd = (num % 10) | ( ((num / 10 ) % 10) << 4 );
72 return bcd;
73 }
74
WCHAR_To_char(WCHAR * src,char * dst,int len)75 static void WCHAR_To_char(WCHAR *src, char *dst, int len)
76 {
77 memset(dst, 0, len * sizeof(char));
78 for (int i = 0; i < len; i++) {
79 memcpy(dst, src, 1);
80 src++;
81 dst++;
82 }
83 }
84
getLoaderSizeAndData(char * loaderName,const unsigned char * data_buf,unsigned char ** loaderBuffer)85 static DWORD getLoaderSizeAndData(char * loaderName, const unsigned char * data_buf, unsigned char **loaderBuffer)
86 {
87
88 DWORD dwOffset;
89 UCHAR ucCount, ucSize;
90 DWORD dwSize = 0;
91
92 dwOffset = pBootHead->dwLoaderEntryOffset;
93 ucCount = pBootHead->ucLoaderEntryCount;
94 ucSize = pBootHead->ucLoaderEntrySize;
95 for (UCHAR i = 0; i < ucCount; i++) {
96 PSTRUCT_RKBOOT_ENTRY pEntry;
97 pEntry = (PSTRUCT_RKBOOT_ENTRY)(data_buf + dwOffset + (ucSize * i));
98
99 char szName[20];
100 WCHAR_To_char(pEntry->szName, szName, 20);
101 if (strcmp(loaderName, szName) == 0) {
102 LOGI("pEntry->szName = %s.\n", szName);
103 dwSize = pEntry->dwDataSize;
104 *loaderBuffer = (unsigned char *)malloc(dwSize);
105 if (*loaderBuffer == NULL) {
106 LOGE("malloc error.\n");
107 }
108 memset(*loaderBuffer, 0, dwSize);
109 memcpy(*loaderBuffer, data_buf + pEntry->dwDataOffset, pEntry->dwDataSize);
110 LOGI("pEntry->dwDataOffset = %d, pEntry->dwDataSize = %d.\n", pEntry->dwDataOffset, pEntry->dwDataSize);
111
112 }
113 }
114 return dwSize;
115 }
116
FindValidBlocks(char bBegin,char bLen,PBYTE pblockState)117 static CHAR FindValidBlocks(char bBegin, char bLen, PBYTE pblockState)
118 {
119 char bCount = 0;
120 char bIndex = bBegin;
121 while (bBegin < IDBLOCK_TOP) {
122 //if(0 == m_flashInfo.blockState[bBegin++])
123 if (0 == pblockState[bBegin++])
124 ++bCount;
125 else {
126 bCount = 0;
127 bIndex = bBegin;
128 }
129 if (bCount >= bLen)
130 break;
131 }
132 if (bBegin >= IDBLOCK_TOP)
133 bIndex = -1;
134
135 return bIndex;
136 }
137
MakeSector0(PBYTE pSector)138 static bool MakeSector0(PBYTE pSector)
139 {
140 PRKANDROID_IDB_SEC0 pSec0;
141 memset(pSector, 0, SECTOR_SIZE);
142 pSec0 = (PRKANDROID_IDB_SEC0)pSector;
143
144 pSec0->dwTag = 0x0FF0AA55;
145 if (m_bRc4Disable) {
146 pSec0->uiRc4Flag = 1;
147 }
148 pSec0->usBootCode1Offset = 0x4;
149 pSec0->usBootCode2Offset = 0x4;
150 pSec0->usBootDataSize = m_usFlashDataSec;
151 pSec0->usBootCodeSize = m_usFlashDataSec + m_usFlashBootSec;
152 return true;
153 }
154
MakeSector1(PBYTE pSector)155 static void MakeSector1(PBYTE pSector)
156 {
157 PRKANDROID_IDB_SEC1 pSec1;
158 memset(pSector, 0, SECTOR_SIZE);
159 pSec1 = (PRKANDROID_IDB_SEC1)pSector;
160 USHORT usSysReserved;
161 if ((m_idBlockOffset[4] + 1) % 12 == 0) {
162 usSysReserved = m_idBlockOffset[4] + 13;
163 } else {
164 usSysReserved = ((m_idBlockOffset[4] + 1) / 12 + 1) * 12;
165 }
166 if (usSysReserved > IDBLOCK_TOP) {
167 usSysReserved = IDBLOCK_TOP;
168 }
169 pSec1->usSysReservedBlock = usSysReserved;
170
171
172 pSec1->usDisk0Size = 0;
173 pSec1->usDisk1Size = 0;
174 pSec1->usDisk2Size = 0;
175 pSec1->usDisk3Size = 0;
176 pSec1->uiChipTag = 0x38324B52;
177 pSec1->uiMachineId = 0;
178
179 pSec1->usLoaderYear = UshortToBCD(pBootHead->stReleaseTime.usYear);
180 pSec1->usLoaderDate = ByteToBCD(pBootHead->stReleaseTime.ucMonth);
181 pSec1->usLoaderDate = (pSec1->usLoaderDate << 8) | ByteToBCD(pBootHead->stReleaseTime.ucDay);
182 pSec1->usLoaderVer = pBootHead->dwVersion;
183
184 pSec1->usLastLoaderVer = 0;
185 pSec1->usReadWriteTimes = 1;
186
187 pSec1->uiFlashSize = m_FlashSize * 1024;
188 LOGI("m_FlashSize * 1024 = %lld.\n", m_FlashSize * 1024);
189 //pSec1->usBlockSize = m_flashInfo.usBlockSize*2;
190 //pSec1->bPageSize = m_flashInfo.uiPageSize*2;
191 //pSec1->bECCBits = m_flashInfo.bECCBits;
192 //pSec1->bAccessTime = m_flashInfo.bAccessTime;
193
194 pSec1->usFlashInfoLen = 0;
195 pSec1->usFlashInfoOffset = 0;
196
197
198 pSec1->usIdBlock0 = m_idBlockOffset[0];
199 pSec1->usIdBlock1 = m_idBlockOffset[1];
200 pSec1->usIdBlock2 = m_idBlockOffset[2];
201 pSec1->usIdBlock3 = m_idBlockOffset[3];
202 pSec1->usIdBlock4 = m_idBlockOffset[4];
203 }
204
MakeSector2(PBYTE pSector)205 static bool MakeSector2(PBYTE pSector)
206 {
207 PRKANDROID_IDB_SEC2 pSec2;
208 pSec2 = (PRKANDROID_IDB_SEC2)pSector;
209
210 pSec2->usInfoSize = 0;
211 memset(pSec2->bChipInfo, 0, CHIPINFO_LEN);
212
213 memset(pSec2->reserved, 0, RKANDROID_SEC2_RESERVED_LEN);
214 pSec2->usSec3CustomDataOffset = 0;//debug
215 pSec2->usSec3CustomDataSize = 0;//debug
216
217 strcpy(pSec2->szVcTag, "VC");
218 strcpy(pSec2->szCrcTag, "CRC");
219 return true;
220 }
MakeSector3(PBYTE pSector)221 static bool MakeSector3(PBYTE pSector)
222 {
223 PRKANDROID_IDB_SEC3 pSec3;
224 memset(pSector, 0, SECTOR_SIZE);
225 pSec3 = (PRKANDROID_IDB_SEC3)pSector;
226 return true;
227 }
228
MakeIDBlockData(PBYTE lpIDBlock,PBYTE loaderCodeBuffer,PBYTE loaderDataBuffer)229 static int MakeIDBlockData(PBYTE lpIDBlock, PBYTE loaderCodeBuffer, PBYTE loaderDataBuffer)
230 {
231
232 RKANDROID_IDB_SEC0 sector0Info;
233 RKANDROID_IDB_SEC1 sector1Info;
234 RKANDROID_IDB_SEC2 sector2Info;
235 RKANDROID_IDB_SEC3 sector3Info;
236
237 MakeSector0((PBYTE)§or0Info);
238 MakeSector1((PBYTE)§or1Info);
239 if (!MakeSector2((PBYTE)§or2Info)) {
240 return -6;
241 }
242
243 if (!MakeSector3((PBYTE)§or3Info)) {
244 return -7;
245 }
246
247 sector2Info.usSec0Crc = CRC_16((PBYTE)§or0Info, SECTOR_SIZE);
248 sector2Info.usSec1Crc = CRC_16((PBYTE)§or1Info, SECTOR_SIZE);
249 sector2Info.usSec3Crc = CRC_16((PBYTE)§or3Info, SECTOR_SIZE);
250 memcpy(lpIDBlock, §or0Info, SECTOR_SIZE);
251 memcpy(lpIDBlock + SECTOR_SIZE, §or1Info, SECTOR_SIZE);
252 memcpy(lpIDBlock + SECTOR_SIZE * 3, §or3Info, SECTOR_SIZE);
253
254 //close rc4 encryption
255 if (sector0Info.uiRc4Flag) {
256 for (int i = 0; i < m_dwLoaderDataSize / SECTOR_SIZE; i++) {
257 P_RC4(loaderDataBuffer + SECTOR_SIZE * i, SECTOR_SIZE);
258 }
259 for (int i = 0; i < m_dwLoaderSize / SECTOR_SIZE; i++) {
260 P_RC4(loaderCodeBuffer + SECTOR_SIZE * i, SECTOR_SIZE);
261 }
262 }
263 memcpy(lpIDBlock + SECTOR_SIZE * 4, loaderDataBuffer, m_dwLoaderDataSize);
264 memcpy(lpIDBlock + SECTOR_SIZE * (4 + m_usFlashDataSec), loaderCodeBuffer, m_dwLoaderSize);
265 sector2Info.uiBootCodeCrc = CRC_32((PBYTE)(lpIDBlock + SECTOR_SIZE * 4), sector0Info.usBootCodeSize * SECTOR_SIZE, 0);
266 memcpy(lpIDBlock + SECTOR_SIZE * 2, §or2Info, SECTOR_SIZE);
267 for (int i = 0; i < 4; i++) {
268 if (i == 1) {
269 continue;
270 } else {
271 P_RC4(lpIDBlock + SECTOR_SIZE * i, SECTOR_SIZE);
272 }
273 }
274 return 0;
275 }
276
calcIDBCount()277 static void calcIDBCount()
278 {
279 uiSecNumPerIDB = 4 + m_usFlashDataSec + m_usFlashBootSec;
280 usPhyBlokcPerIDB = ((uiSecNumPerIDB > 0) ? ((uiSecNumPerIDB - 1) / 8 + 1) : (uiSecNumPerIDB));
281 LOGI("usPhyBlokcPerIDB = %d.\n", usPhyBlokcPerIDB);
282 }
283
reserveIDBlock()284 static int reserveIDBlock()
285 {
286 // 3. ReserveIDBlock
287 CHAR iRet;
288 char iBlockIndex = 0;
289
290 BYTE blockState[IDBLOCK_TOP];
291 memset(m_idBlockOffset, 0, sizeof(DWORD)*IDB_BLOCKS);
292 memset(blockState, 0, IDBLOCK_TOP);
293 for (char i = 0; i < IDB_BLOCKS; i++) {
294 iRet = iBlockIndex = FindValidBlocks(iBlockIndex, usPhyBlokcPerIDB, blockState);
295 if (iRet < 0 ) {
296 return -1;
297 LOGE("FindValidBlocks Error.\n");
298 }
299 m_idBlockOffset[i] = iBlockIndex;
300 iBlockIndex += usPhyBlokcPerIDB;
301 }
302
303 return 0;
304 }
305
WriteIDBlock(PBYTE lpIDBlock,DWORD dwSectorNum,char * dest_path)306 static int WriteIDBlock(PBYTE lpIDBlock, DWORD dwSectorNum, char *dest_path)
307 {
308 LOGE("WriteIDBlock start %s \n", dest_path);
309 // int fd_dest = open("/tmp/loader2.txt", O_RDWR|O_SYNC, 0);
310 int fd_dest = open(dest_path, O_CREAT | O_RDWR | O_SYNC | O_TRUNC, 0);
311 if (fd_dest < 0) {
312 LOGE("WriteIDBlock open %s failed. %s\n", dest_path, strerror(errno));
313 return -2;
314 }
315
316 for (int i = 0; i <= 4; i++) {
317 //debug for 3308
318 //256 为128k 的起始位置
319 //每256k 备份一份
320 lseek64(fd_dest, (i * 512)*SECTOR_SIZE, SEEK_SET);
321 if (write(fd_dest, lpIDBlock, dwSectorNum * SECTOR_SIZE) != dwSectorNum * SECTOR_SIZE) {
322 close(fd_dest);
323 LOGE("[%s:%d] error (%s).\n", __func__, __LINE__, strerror(errno));
324 return -1;
325 }
326 }
327 sync();
328 close(fd_dest);
329 return 0;
330 }
331
download_loader(PBYTE data_buf,int size,char * dest_path)332 bool download_loader(PBYTE data_buf, int size, char *dest_path)
333 {
334 generate_gf();
335 gen_poly();
336
337 if (getFlashInfo(NULL, &uiFlashBlockSize, &uiFlashPageSize) != 0) {
338 LOGE("%s-%d: get mtd info error\n", __func__, __LINE__);
339 return false;
340 }
341 // 1. 获取头部信息,和文件内容
342 pBootHead = (PSTRUCT_RKBOOT_HEAD)(data_buf);
343
344 if (pBootHead->uiTag != 0x544F4F42 && pBootHead->uiTag != 0x2052444C) {
345 LOGE("pBootHead->uiTag!=0x544F4F42 && pBootHead->uiTag!=0x2052444C, cur is 0x%08x\n", pBootHead->uiTag );
346 return false;
347 }
348
349 if (pBootHead->ucRc4Flag) {
350 m_bRc4Disable = true;
351 } else {
352 m_bRc4Disable = false;
353 }
354
355 char loaderDataName[] = "FlashData";
356 unsigned char *loaderDataBuffer = NULL;
357 m_dwLoaderDataSize = getLoaderSizeAndData(loaderDataName, data_buf, &loaderDataBuffer);
358 m_usFlashDataSec = PAGEALIGN(BYTE2SECTOR(m_dwLoaderDataSize)) * 4;
359 LOGI("m_usFlashDataSec = %d, m_dwLoaderDataSize = %d.\n", m_usFlashDataSec, m_dwLoaderDataSize);
360
361 char loaderName[] = "FlashBoot";
362 unsigned char *loaderCodeBuffer = NULL;
363 m_dwLoaderSize = getLoaderSizeAndData(loaderName, data_buf, &loaderCodeBuffer);
364 m_usFlashBootSec = PAGEALIGN(BYTE2SECTOR(m_dwLoaderSize)) * 4;
365 LOGI("m_usFlashBootSec = %d, m_dwLoaderSize = %d.\n", m_usFlashBootSec, m_dwLoaderSize);
366
367 calcIDBCount();
368 reserveIDBlock();
369
370 // 4. MakeIDBlockData
371 if (getFlashSize(dest_path, &m_FlashSize, &m_FlasBlockNum) != 0) {
372 LOGE("getFlashSize error.\n");
373 return false;
374 }
375 LOGI("[%s:%d] m_FlashSize [%lld]\n", __func__, __LINE__, m_FlashSize);
376
377 // 5. download IDBlock
378 PBYTE pIDBData = NULL;
379 pIDBData = (PBYTE)malloc(uiSecNumPerIDB * SECTOR_SIZE);
380 if ( !pIDBData )
381 return false;
382 memset(pIDBData, 0, uiSecNumPerIDB * SECTOR_SIZE);
383 if (MakeIDBlockData(pIDBData, loaderCodeBuffer, loaderDataBuffer) != 0 ) {
384 LOGE("[%s:%d] MakeIDBlockData failed.\n", __func__, __LINE__);
385 return false;
386 }
387
388 if (WriteIDBlock(pIDBData, uiSecNumPerIDB, dest_path) != 0) {
389 LOGE("[%s:%d] WriteIDBlock failed.\n", __func__, __LINE__);
390 return false;
391 }
392 free(pIDBData);
393 free(loaderCodeBuffer);
394 free(loaderDataBuffer);
395
396 return true;
397 }
398
399