xref: /OK3568_Linux_fs/external/recovery/update_engine/rkboot.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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)&sector0Info);
238     MakeSector1((PBYTE)&sector1Info);
239     if (!MakeSector2((PBYTE)&sector2Info)) {
240         return -6;
241     }
242 
243     if (!MakeSector3((PBYTE)&sector3Info)) {
244         return -7;
245     }
246 
247     sector2Info.usSec0Crc = CRC_16((PBYTE)&sector0Info, SECTOR_SIZE);
248     sector2Info.usSec1Crc = CRC_16((PBYTE)&sector1Info, SECTOR_SIZE);
249     sector2Info.usSec3Crc = CRC_16((PBYTE)&sector3Info, SECTOR_SIZE);
250     memcpy(lpIDBlock, &sector0Info, SECTOR_SIZE);
251     memcpy(lpIDBlock + SECTOR_SIZE, &sector1Info, SECTOR_SIZE);
252     memcpy(lpIDBlock + SECTOR_SIZE * 3, &sector3Info, 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, &sector2Info, 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