xref: /OK3568_Linux_fs/external/recovery/update_engine/rkimage.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (C) 2023 Rockchip Electronics Co., Ltd.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Licensed under the Apache License, Version 2.0 (the "License");
5*4882a593Smuzhiyun  * you may not use this file except in compliance with the License.
6*4882a593Smuzhiyun  * You may obtain a copy of the License at
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  *       http://www.apache.org/licenses/LICENSE-2.0
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * Unless required by applicable law or agreed to in writing, software
11*4882a593Smuzhiyun  * distributed under the License is distributed on an "AS IS" BASIS,
12*4882a593Smuzhiyun  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4882a593Smuzhiyun  * See the License for the specific language governing permissions and
14*4882a593Smuzhiyun  * limitations under the License.
15*4882a593Smuzhiyun  */
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include <stdio.h>
18*4882a593Smuzhiyun #include <sys/types.h>
19*4882a593Smuzhiyun #include <sys/stat.h>
20*4882a593Smuzhiyun #include <fcntl.h>
21*4882a593Smuzhiyun #include <unistd.h>
22*4882a593Smuzhiyun #include <string.h>
23*4882a593Smuzhiyun #include <errno.h>
24*4882a593Smuzhiyun #include <stdbool.h>
25*4882a593Smuzhiyun #include "rkimage.h"
26*4882a593Smuzhiyun #include "log.h"
27*4882a593Smuzhiyun #include "md5sum.h"
28*4882a593Smuzhiyun #include "rktools.h"
29*4882a593Smuzhiyun #include "update.h"
30*4882a593Smuzhiyun 
display_head(PSTRUCT_RKIMAGE_HEAD pHead)31*4882a593Smuzhiyun static void display_head(PSTRUCT_RKIMAGE_HEAD pHead)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun     LOGD("uiTag = %x.\n", pHead->uiTag);
34*4882a593Smuzhiyun     LOGD("usSize = %x.\n", pHead->usSize);
35*4882a593Smuzhiyun     LOGD("dwVersion = %x.\n", pHead->dwVersion);
36*4882a593Smuzhiyun     UINT btMajor = ((pHead->dwVersion) & 0XFF000000) >> 24;
37*4882a593Smuzhiyun     UINT btMinor = ((pHead->dwVersion) & 0X00FF0000) >> 16;
38*4882a593Smuzhiyun     UINT usSmall = ((pHead->dwVersion) & 0x0000FFFF);
39*4882a593Smuzhiyun     LOGD("btMajor = %x, btMinor = %x, usSmall = %02x.\n", btMajor, btMinor, usSmall);
40*4882a593Smuzhiyun     LOGD("dwBootOffset = %x.\n", pHead->dwBootOffset);
41*4882a593Smuzhiyun     LOGD("dwBootSize = %x.\n", pHead->dwBootSize);
42*4882a593Smuzhiyun     LOGD("dwFWOffset = %x.\n", pHead->dwFWOffset);
43*4882a593Smuzhiyun     LOGD("dwFWSize = %x.\n", pHead->dwFWSize);
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun 
display_item(PRKIMAGE_ITEM pitem)46*4882a593Smuzhiyun static void display_item(PRKIMAGE_ITEM pitem)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun     //char name[PART_NAME];
49*4882a593Smuzhiyun     //char file[RELATIVE_PATH];
50*4882a593Smuzhiyun     //unsigned int offset;
51*4882a593Smuzhiyun     //unsigned int flash_offset;
52*4882a593Smuzhiyun     //unsigned int usespace;
53*4882a593Smuzhiyun     //unsigned int size;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun     LOGD("name = %s\n", pitem->name);
56*4882a593Smuzhiyun     LOGD("file = %s\n", pitem->file);
57*4882a593Smuzhiyun     LOGD("offset = %d\n", pitem->offset);
58*4882a593Smuzhiyun     LOGD("flash_offset = %d\n", pitem->flash_offset);
59*4882a593Smuzhiyun     LOGD("usespace = %d\n", pitem->usespace);
60*4882a593Smuzhiyun     LOGD("size = %d\n", pitem->size);
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun 
display_hdr(PRKIMAGE_HDR phdr)63*4882a593Smuzhiyun static void display_hdr(PRKIMAGE_HDR phdr)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun     //unsigned int tag;
67*4882a593Smuzhiyun     //unsigned int size;
68*4882a593Smuzhiyun     //char machine_model[MAX_MACHINE_MODEL];
69*4882a593Smuzhiyun     //char manufacturer[MAX_MANUFACTURER];
70*4882a593Smuzhiyun     //unsigned int version;
71*4882a593Smuzhiyun     //int item_count;
72*4882a593Smuzhiyun     //RKIMAGE_ITEM item[MAX_PACKAGE_FILES];
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun     LOGD("tag = %d\n", phdr->tag);
75*4882a593Smuzhiyun     LOGD("size = %d\n", phdr->size);
76*4882a593Smuzhiyun     LOGD("machine_model = %s\n", phdr->machine_model);
77*4882a593Smuzhiyun     LOGD("manufacturer = %s\n", phdr->manufacturer);
78*4882a593Smuzhiyun     LOGD("version = %d\n", phdr->version);
79*4882a593Smuzhiyun     LOGD("item = %d.\n", phdr->item_count);
80*4882a593Smuzhiyun     for (int i = 0; i < phdr->item_count; i++) {
81*4882a593Smuzhiyun         LOGI("================================================\n");
82*4882a593Smuzhiyun         display_item(&(phdr->item[i]));
83*4882a593Smuzhiyun     }
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun 
adjustFileOffset(PRKIMAGE_HDR phdr,int offset,int loader_offset,int loader_size)86*4882a593Smuzhiyun void adjustFileOffset(PRKIMAGE_HDR phdr, int offset, int loader_offset, int loader_size)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun     for (int i = 0; i < phdr->item_count; i++) {
89*4882a593Smuzhiyun         if ( strcmp(phdr->item[i].name, "bootloader") == 0) {
90*4882a593Smuzhiyun             phdr->item[i].offset = loader_offset;
91*4882a593Smuzhiyun             phdr->item[i].size = loader_size;
92*4882a593Smuzhiyun             continue ;
93*4882a593Smuzhiyun         }
94*4882a593Smuzhiyun         phdr->item[i].offset += offset;
95*4882a593Smuzhiyun     }
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun //解析固件,获得固件头部信息
analyticImage(const char * filepath,PRKIMAGE_HDR phdr)99*4882a593Smuzhiyun int analyticImage(const char *filepath, PRKIMAGE_HDR phdr)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun     long long ulFwSize;
102*4882a593Smuzhiyun     STRUCT_RKIMAGE_HEAD rkimage_head;
103*4882a593Smuzhiyun     unsigned char m_md5[32];
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun     int fd = open(filepath, O_RDONLY);
107*4882a593Smuzhiyun     if (fd < 0) {
108*4882a593Smuzhiyun         LOGE("Can't open %s\n", filepath);
109*4882a593Smuzhiyun         return -2;
110*4882a593Smuzhiyun     }
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun     //1. image 头部信息读取
113*4882a593Smuzhiyun     if (read(fd, &rkimage_head, sizeof(STRUCT_RKIMAGE_HEAD)) != sizeof(STRUCT_RKIMAGE_HEAD)) {
114*4882a593Smuzhiyun         LOGE("Can't read %s\n(%s)\n", filepath, strerror(errno));
115*4882a593Smuzhiyun         close(fd);
116*4882a593Smuzhiyun         return -2;
117*4882a593Smuzhiyun     }
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun     if ((rkimage_head.reserved[14] == 'H') && (rkimage_head.reserved[15] == 'I')) {
120*4882a593Smuzhiyun         ulFwSize = *((DWORD *)(&rkimage_head.reserved[16]));
121*4882a593Smuzhiyun         ulFwSize <<= 32;
122*4882a593Smuzhiyun         ulFwSize += rkimage_head.dwFWOffset;
123*4882a593Smuzhiyun         ulFwSize += rkimage_head.dwFWSize;
124*4882a593Smuzhiyun     } else {
125*4882a593Smuzhiyun         ulFwSize = rkimage_head.dwFWOffset + rkimage_head.dwFWSize;
126*4882a593Smuzhiyun     }
127*4882a593Smuzhiyun     rkimage_head.dwFWSize = ulFwSize - rkimage_head.dwFWOffset;
128*4882a593Smuzhiyun     display_head(&rkimage_head);
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun     //2. 固件md5 校验
131*4882a593Smuzhiyun     long long fileSize;
132*4882a593Smuzhiyun     int nMd5DataSize;
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun     fileSize = lseek64(fd, 0L, SEEK_END);
135*4882a593Smuzhiyun     nMd5DataSize = fileSize - ulFwSize;
136*4882a593Smuzhiyun     if (nMd5DataSize >= 160) {
137*4882a593Smuzhiyun         LOGE("md5 : not support sign image.\n");
138*4882a593Smuzhiyun         //sign image
139*4882a593Smuzhiyun         //m_bSignFlag = true;
140*4882a593Smuzhiyun         //m_signMd5Size = nMd5DataSize-32;
141*4882a593Smuzhiyun         //fseeko64(m_pFile,ulFwSize,SEEK_SET);
142*4882a593Smuzhiyun         //fread(m_md5,1,32,m_pFile);
143*4882a593Smuzhiyun         //fread(m_signMd5,1,nMd5DataSize-32,m_pFile);
144*4882a593Smuzhiyun     } else {
145*4882a593Smuzhiyun         lseek64(fd, -32, SEEK_END);
146*4882a593Smuzhiyun         if ( read(fd, m_md5, 32) != 32) {
147*4882a593Smuzhiyun             LOGE("lseek failed.\n");
148*4882a593Smuzhiyun             close(fd);
149*4882a593Smuzhiyun             return -2;
150*4882a593Smuzhiyun         }
151*4882a593Smuzhiyun     }
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun     //3. image 地址信息读取
154*4882a593Smuzhiyun     if (lseek64(fd, rkimage_head.dwFWOffset, SEEK_SET) == -1) {
155*4882a593Smuzhiyun         LOGE("lseek failed.\n");
156*4882a593Smuzhiyun         close(fd);
157*4882a593Smuzhiyun         return -2;
158*4882a593Smuzhiyun     }
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun     if (read(fd, phdr, sizeof(RKIMAGE_HDR)) != sizeof(RKIMAGE_HDR)) {
161*4882a593Smuzhiyun         LOGE("Can't read %s\n(%s)\n", filepath, strerror(errno));
162*4882a593Smuzhiyun         close(fd);
163*4882a593Smuzhiyun         return -2;
164*4882a593Smuzhiyun     }
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun     if (phdr->tag != RKIMAGE_TAG) {
167*4882a593Smuzhiyun         LOGE("tag: %x\n", phdr->tag);
168*4882a593Smuzhiyun         LOGE("Invalid image\n");
169*4882a593Smuzhiyun         close(fd);
170*4882a593Smuzhiyun         return -3;
171*4882a593Smuzhiyun     }
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun     if ((phdr->manufacturer[56] == 0x55) && (phdr->manufacturer[57] == 0x66)) {
174*4882a593Smuzhiyun         USHORT *pItemRemain;
175*4882a593Smuzhiyun         pItemRemain = (USHORT *)(&phdr->manufacturer[58]);
176*4882a593Smuzhiyun         phdr->item_count += *pItemRemain;
177*4882a593Smuzhiyun     }
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun     if (rkimage_head.dwFWOffset) {
180*4882a593Smuzhiyun         adjustFileOffset(phdr, rkimage_head.dwFWOffset, rkimage_head.dwBootOffset, rkimage_head.dwBootSize);
181*4882a593Smuzhiyun     }
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun     display_hdr(phdr);
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun     close(fd);
186*4882a593Smuzhiyun #if 1
187*4882a593Smuzhiyun     if (!compareMd5sum((char*)filepath, m_md5, 0, fileSize - 32)) {
188*4882a593Smuzhiyun         LOGE("Md5Check update.img fwSize:%ld", fileSize - 32);
189*4882a593Smuzhiyun         return -1;
190*4882a593Smuzhiyun     }
191*4882a593Smuzhiyun #endif
192*4882a593Smuzhiyun     LOGI("analyticImage ok.\n");
193*4882a593Smuzhiyun     return 0;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun // 获得Image 打包版本号
getImageVersion(const char * filepath,char * version,int maxLength)197*4882a593Smuzhiyun bool getImageVersion(const char *filepath, char *version, int maxLength)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun     STRUCT_RKIMAGE_HEAD rkimage_head;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun     int fd = open(filepath, O_RDONLY);
202*4882a593Smuzhiyun     if (fd < 0) {
203*4882a593Smuzhiyun         LOGE("Can't open %s\n", filepath);
204*4882a593Smuzhiyun         return false;
205*4882a593Smuzhiyun     }
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun     //1. image 头部信息读取
208*4882a593Smuzhiyun     if (read(fd, &rkimage_head, sizeof(STRUCT_RKIMAGE_HEAD)) != sizeof(STRUCT_RKIMAGE_HEAD)) {
209*4882a593Smuzhiyun         LOGE("Can't read %s\n(%s)\n", filepath, strerror(errno));
210*4882a593Smuzhiyun         close(fd);
211*4882a593Smuzhiyun         return false;
212*4882a593Smuzhiyun     }
213*4882a593Smuzhiyun     close(fd);
214*4882a593Smuzhiyun     UINT btMajor = ((rkimage_head.dwVersion) & 0XFF000000) >> 24;
215*4882a593Smuzhiyun     UINT btMinor = ((rkimage_head.dwVersion) & 0x00FF0000) >> 16;
216*4882a593Smuzhiyun     UINT usSmall = ((rkimage_head.dwVersion) & 0x0000FFFF);
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun     //转换成字符串
219*4882a593Smuzhiyun     sprintf(version, "%d.%d.%d", btMajor, btMinor, usSmall);
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun     return true;
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun #if 0
225*4882a593Smuzhiyun int main(int argc, char *argv[])
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun     analyticImage(argv[1]);
228*4882a593Smuzhiyun     compareVersion();
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun #endif
231