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