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