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 <unistd.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <libgen.h>
26 #include <limits.h>
27 #include <stdbool.h>
28 #include "flash_image.h"
29 #include "update.h"
30 #include "log.h"
31 #include "rktools.h"
32 #include "gpt.h"
33 #include "rkimage.h"
34 #include "defineHeader.h"
35 #include "rkboot.h"
36 #include "../mtdutils/mtdutils.h"
37
38
39 #define UBI_HEAD_MAGIC "UBI#"
40
41 static PSTRUCT_PARAM_ITEM gp_param_item = NULL;
42 static long long *gp_backup_gpt_offset = NULL;
43
44 // get greastest common divisor (gcd)
get_gcd(long long x,long long y)45 static int get_gcd ( long long x, long long y )
46 {
47 while (x != y) { //用大数减去小数并将结果保存起来
48 if (x > y) {
49 x -= y;
50 } else if (x < y) {
51 y -= x;
52 }
53 }
54 return x;
55 }
56
is_ubi(char * src_path,long long offset)57 static bool is_ubi(char *src_path, long long offset)
58 {
59 char magic[5] = {0};
60 bool ret;
61
62 int fd_src = open(src_path, O_RDONLY);
63 if (fd_src < 0) {
64 LOGE("error opening %s.\n", src_path);
65 return 0;
66 }
67 if ( lseek64(fd_src, offset, SEEK_SET) == -1) {
68 close(fd_src);
69 LOGE("lseek64 failed (%s:%d).\n", __func__, __LINE__);
70 return 0;
71 }
72 read(fd_src, magic, 4);
73 LOGI("image magic is %s\n", magic);
74 if (strcmp(magic, UBI_HEAD_MAGIC) == 0)
75 ret = 1;
76 else
77 ret = 0;
78 close(fd_src);
79
80 return ret;
81 }
82
mtd_read()83 static void mtd_read()
84 {
85
86 }
87
mtd_write(char * src_path,long long offset,long long size,long long flash_offset,char * dest_path)88 static int mtd_write(char *src_path, long long offset, long long size, long long flash_offset, char *dest_path)
89 {
90 LOGI("mtd_write %s, offset = %#llx size = %#llx flash_offset = %lld.\n", dest_path, offset, size, flash_offset);
91
92 struct stat sb;
93 char mtd_write_erase_cmd[256] = {0};
94 int system_ret;
95 stat(dest_path, &sb);
96 long long dd_bs = 1;
97 long long dd_skip = offset;
98 long long dd_count = size;
99
100 if ((sb.st_mode & S_IFMT) == S_IFCHR) {
101 memset(mtd_write_erase_cmd, 0, sizeof(mtd_write_erase_cmd) / sizeof(mtd_write_erase_cmd[0]));
102 sprintf(mtd_write_erase_cmd, "flash_erase %s 0 0", dest_path);
103 system_ret = system(mtd_write_erase_cmd);
104
105 dd_bs = get_gcd(offset, size);
106 dd_skip = offset / dd_bs;
107 dd_count = size / dd_bs;
108 // dd if=/mnt/sdcard/sdupdate.img bs=4 skip=2727533 count=3646464 | nandwrite -p /dev/block/by-name/recovery
109 memset(mtd_write_erase_cmd, 0, sizeof(mtd_write_erase_cmd) / sizeof(mtd_write_erase_cmd[0]));
110 sprintf(mtd_write_erase_cmd, "dd if=%s bs=%lld skip=%lld count=%lld | nandwrite -p %s",
111 src_path, dd_bs, dd_skip, dd_count, dest_path );
112 system_ret = system(mtd_write_erase_cmd);
113 } else {
114 LOGE("flash_erase: can't erase MTD \"%s\"\n", dest_path);
115 return -1;
116 }
117
118 return 0;
119 }
120
block_read()121 static void block_read()
122 {
123
124 }
125
block_write(char * src_path,long long offset,long long size,long long flash_offset,char * dest_path)126 static int block_write(char *src_path, long long offset, long long size, long long flash_offset, char *dest_path)
127 {
128 LOGI("block_write src %s dest %s.\n", src_path, dest_path);
129 int fd_dest = 0, fd_src = 0;
130 long long src_offset = 0, dest_offset = 0;
131 long long src_remain, dest_remain;
132 int src_step, dest_step;
133 long long src_file_offset = 0;
134 long long read_count, write_count;
135 char data_buf[BLOCK_WRITE_LEN] = {0};
136
137 fd_src = open(src_path, O_RDONLY);
138 if (fd_src < 0) {
139 LOGE("Can't open %s\n", src_path);
140 return -2;
141 }
142 src_offset = offset;
143 dest_remain = src_remain = size;
144 dest_step = src_step = BLOCK_WRITE_LEN;
145
146 if (lseek64(fd_src, src_offset, SEEK_SET) == -1) {
147 close(fd_src);
148 LOGE("lseek64 failed (%s:%d).\n", __func__, __LINE__);
149 return -2;
150 }
151 src_file_offset = src_offset;
152 // dest_offset = flash_offset;
153 // This step is going to write (src_path: sdupdate.img) to the file which is partition data (e.g. uboot)
154 // So dest_offset is 0.
155 dest_offset = 0;
156
157 fd_dest = open(dest_path, O_RDWR | O_CREAT | O_TRUNC, 0644);
158 if (fd_dest < 0) {
159 close(fd_src);
160 LOGE("Can't open %s\n", dest_path);
161 return -2;
162 }
163 if ( lseek64(fd_dest, dest_offset, SEEK_SET) == -1 ) {
164 LOGE("(%s:%d) lseek64 failed(%s).\n", __func__, __LINE__, strerror(errno));
165 close(fd_src);
166 close(fd_dest);
167 return -2;
168 }
169 while (src_remain > 0 && dest_remain > 0) {
170 memset(data_buf, 0, BLOCK_WRITE_LEN);
171 read_count = src_remain > src_step ? src_step : src_remain;
172
173 if (read(fd_src, data_buf, read_count) != read_count) {
174 close(fd_dest);
175 close(fd_src);
176 LOGE("Read failed(%s):(%s:%d)\n", strerror(errno), __func__, __LINE__);
177 return -2;
178 }
179
180 src_remain -= read_count;
181 src_file_offset += read_count;
182 write_count = dest_remain > dest_step ? dest_step : dest_remain;
183
184 if (write(fd_dest, data_buf, write_count) != write_count) {
185 close(fd_dest);
186 close(fd_src);
187 LOGE("(%s:%d) write failed(%s).\n", __func__, __LINE__, strerror(errno));
188 return -2;
189 }
190 dest_remain -= write_count;
191 }
192
193 fsync(fd_dest);
194 close(fd_dest);
195 close(fd_src);
196 return 0;
197 }
198
199 extern int do_patch_rkimg(const char *img, ssize_t offset, ssize_t size,
200 const char *blk_dev, const char *dst_file);
201
202 extern bool is_sdboot;
flash_normal(char * src_path,void * pupdate_cmd)203 int flash_normal(char *src_path, void *pupdate_cmd)
204 {
205 LOGI("%s:%d start.\n", __func__, __LINE__);
206 PUPDATE_CMD pcmd = (PUPDATE_CMD)pupdate_cmd;
207 int ret = 0;
208
209 if (is_sdboot || !isMtdDevice()) {
210 //block
211 char dst_file[256];
212 /* record the already upgraded img name,
213 * so it can continue on upgrading after unexpected shutdown/reboot
214 */
215 char done_file[256];
216 /* The pattern writes to done_file, e.g.
217 * >uboot<
218 * >boot<
219 * >rootfs<
220 */
221 char pattern[64];
222 int fd;
223 off_t size, len;
224 char buf[512];
225 struct stat dst_stat;
226
227 LOGI("%s:%d, diff check for %s\n", __func__, __LINE__, pcmd->name);
228 snprintf(dst_file, 256, "%s.%s", src_path, pcmd->name);
229 snprintf(done_file, 256, "%s.done", src_path);
230 if ((fd = open(done_file, O_RDWR | O_CREAT | O_DSYNC, 0)) < 0 ||
231 (size = lseek(fd, 0, SEEK_END) < 0) ||
232 (lseek(fd, 0, SEEK_SET) < 0)) {
233 LOGE("open %s failed, upgrading abort!\n", done_file);
234 return -1;
235 }
236 memset(buf, 0, 512);
237 len = 0;
238 while (size > 0 && len != size) {
239 ssize_t val;
240 if ((val = read(fd, buf + len, size - len)) < 0) {
241 close(fd);
242 LOGE("read %s failed: %s\n", done_file, strerror(errno));
243 return val;
244 }
245 len += val;
246 }
247 snprintf(pattern, 64, ">%s<", pcmd->name);
248 /* If this partition already upgraded,
249 * the old image (in flash) could be broken,
250 * it's fine to skip it.
251 */
252 if (strstr(buf, pattern) != NULL) {
253 close(fd);
254 return 0;
255 }
256 /* Otherwise, we shall look inside to make sure:
257 * do_patch_rkimg() can generate a corrent new image even if
258 * machine could lost-power/crash during upgrading
259 * By doing this, do_patch_rkimg() will checking:
260 * - if dst_file already exist
261 * - md5sum is correct, then we may reboot during writing-to-flash
262 * >> do not do patch again.
263 * - md5sum is wrong, then we may reboot during do_patch_rkimg()
264 * >> the old image (in flash) good enough as is, do patch again.
265 * - if dst_file is not exist
266 * - this is normal case, we're safe to continue
267 */
268 if (stat(dst_file, &dst_stat) == 0)
269 LOGI("file %s exist for <%s>, unexpected detected, trying to continue\n",
270 dst_file, pcmd->name);
271 ret = do_patch_rkimg(src_path, pcmd->offset, pcmd->size,
272 pcmd->dest_path, dst_file);
273 if (ret == 0) {
274 ret = block_write(src_path, pcmd->offset, pcmd->size,
275 pcmd->flash_offset, pcmd->dest_path);
276 } else if (ret > 0) {
277 ret = block_write(dst_file, 0, ret,
278 pcmd->flash_offset, pcmd->dest_path);
279 //TODO: do not skip diff image verify
280 pcmd->skip_verify = true;
281 } else {
282 return ret;
283 }
284
285 lseek(fd, 0, SEEK_END);
286 if (write(fd, pattern, strlen(pattern)) != strlen(pattern)) {
287 LOGW("write len error");
288 }
289 close(fd);
290
291 sync();
292 /* Make sure that dst file written to flash before unlink it */
293 unlink(dst_file);
294 sync();
295 } else {
296 //mtd
297 LOGI("pcmd->flash_offset = %lld.\n", pcmd->flash_offset);
298 ret = mtd_write(src_path, pcmd->offset, pcmd->size, pcmd->flash_offset, pcmd->dest_path);
299 }
300 return ret;
301 }
302
string_to_uuid(char * strUUid,char * uuid)303 static void string_to_uuid(char* strUUid, char *uuid)
304 {
305 unsigned int i;
306 char value;
307 memset(uuid, 0, 16);
308 for (i = 0; i < 256; i++) {
309 if (strUUid[i] == '\0') {
310 break;
311 }
312 value = 0;
313 if ((strUUid[i] >= '0') && (strUUid[i] <= '9'))
314 value = strUUid[i] - '0';
315 if ((strUUid[i] >= 'a') && (strUUid[i] <= 'f'))
316 value = strUUid[i] - 'a' + 10;
317 if ((strUUid[i] >= 'A') && (strUUid[i] <= 'F'))
318 value = strUUid[i] - 'A' + 10;
319 if ((i % 2) == 0)
320 uuid[i / 2] += (value << 4);
321 else
322 uuid[i / 2] += value;
323 }
324 unsigned int *p32;
325 unsigned short *p16;
326 p32 = (unsigned int*)uuid;
327 *p32 = cpu_to_be32(*p32);
328 p16 = (unsigned short *)(uuid + 4);
329 *p16 = cpu_to_be16(*p16);
330 p16 = (unsigned short *)(uuid + 6);
331 *p16 = cpu_to_be16(*p16);
332 }
333
getUuidFromString(char * str,PSTRUCT_CONFIG_ITEM p_config)334 static void getUuidFromString(char *str, PSTRUCT_CONFIG_ITEM p_config)
335 {
336 char data_buf[strlen(str)];
337 memcpy(data_buf, str, strlen(str));
338 char *line = strtok(data_buf, "\n");
339 while (line != NULL) {
340 if (line[0] == '#') {
341 continue;
342 }
343
344 char *pline = strstr(line, "uuid");
345 if (pline != NULL && (pline = strstr(pline, ":")) != NULL) {
346 pline++; //过滤掉冒号
347 //过滤掉空格
348 while (*pline == ' ') {
349 pline++;
350 }
351 char tmp;
352 char value[256] = {0};
353 sscanf(pline, "%[^=]%c%s", p_config->name, &tmp, value);
354 string_to_uuid(value, p_config->value);
355 p_config++;
356 }
357
358 line = strtok(NULL, "\n");
359 }
360 }
361
getParamFromString(char * str,PSTRUCT_PARAM_ITEM p_param)362 static void getParamFromString(char *str, PSTRUCT_PARAM_ITEM p_param)
363 {
364 char data_buf[strlen(str)];
365 memcpy(data_buf, str, strlen(str));
366 char *line = strtok(data_buf, "\n");
367 while (line != NULL) {
368 if (line[0] == '#') {
369 continue;
370 }
371
372 char *pline = strstr(line, "mtdparts");
373 if (pline != NULL && (pline = strstr(pline, ":")) != NULL) {
374 pline++; //过滤掉冒号
375 //过滤掉空格
376 while (*pline == ' ') {
377 pline++;
378 }
379 int pline_len = strlen(pline);
380 char mtdparts_line[pline_len];
381 memset(mtdparts_line, 0, pline_len);
382 memcpy(mtdparts_line, pline, pline_len);
383 //开始解析文件
384 char *token = strtok(mtdparts_line, ",");
385 while (token != NULL) {
386 char size[20], offset[20];
387 char tmp;
388 if (*token == '-') {
389 sscanf(token, "-@0x%x(%[^)]", &p_param->offset, p_param->name);
390 p_param->size = 0xFFFFFFFF;
391 p_param++;
392 } else {
393 sscanf(token, "0x%x@0x%x(%[^)]", &p_param->size, &p_param->offset, p_param->name);
394 p_param++;
395 }
396 token = strtok(NULL, ",");
397 }
398 }
399 line = strtok(NULL, "\n");
400 }
401 }
402
gen_rand_uuid(unsigned char * uuid_bin)403 static void gen_rand_uuid(unsigned char *uuid_bin)
404 {
405 efi_guid_t id;
406 unsigned int *ptr = (unsigned int *)&id;
407 unsigned int i;
408
409 /* Set all fields randomly */
410 for (i = 0; i < sizeof(id) / sizeof(*ptr); i++)
411 *(ptr + i) = cpu_to_be32(rand());
412
413 id.uuid.time_hi_and_version = (id.uuid.time_hi_and_version & 0x0FFF) | 0x4000;
414 id.uuid.clock_seq_hi_and_reserved = id.uuid.clock_seq_hi_and_reserved | 0x80;
415
416 memcpy(uuid_bin, id.raw, sizeof(id));
417 }
418
419 #define tole(x) (x)
420 unsigned int crc32table_le[] = {
421 tole(0x00000000L), tole(0x77073096L), tole(0xee0e612cL), tole(0x990951baL),
422 tole(0x076dc419L), tole(0x706af48fL), tole(0xe963a535L), tole(0x9e6495a3L),
423 tole(0x0edb8832L), tole(0x79dcb8a4L), tole(0xe0d5e91eL), tole(0x97d2d988L),
424 tole(0x09b64c2bL), tole(0x7eb17cbdL), tole(0xe7b82d07L), tole(0x90bf1d91L),
425 tole(0x1db71064L), tole(0x6ab020f2L), tole(0xf3b97148L), tole(0x84be41deL),
426 tole(0x1adad47dL), tole(0x6ddde4ebL), tole(0xf4d4b551L), tole(0x83d385c7L),
427 tole(0x136c9856L), tole(0x646ba8c0L), tole(0xfd62f97aL), tole(0x8a65c9ecL),
428 tole(0x14015c4fL), tole(0x63066cd9L), tole(0xfa0f3d63L), tole(0x8d080df5L),
429 tole(0x3b6e20c8L), tole(0x4c69105eL), tole(0xd56041e4L), tole(0xa2677172L),
430 tole(0x3c03e4d1L), tole(0x4b04d447L), tole(0xd20d85fdL), tole(0xa50ab56bL),
431 tole(0x35b5a8faL), tole(0x42b2986cL), tole(0xdbbbc9d6L), tole(0xacbcf940L),
432 tole(0x32d86ce3L), tole(0x45df5c75L), tole(0xdcd60dcfL), tole(0xabd13d59L),
433 tole(0x26d930acL), tole(0x51de003aL), tole(0xc8d75180L), tole(0xbfd06116L),
434 tole(0x21b4f4b5L), tole(0x56b3c423L), tole(0xcfba9599L), tole(0xb8bda50fL),
435 tole(0x2802b89eL), tole(0x5f058808L), tole(0xc60cd9b2L), tole(0xb10be924L),
436 tole(0x2f6f7c87L), tole(0x58684c11L), tole(0xc1611dabL), tole(0xb6662d3dL),
437 tole(0x76dc4190L), tole(0x01db7106L), tole(0x98d220bcL), tole(0xefd5102aL),
438 tole(0x71b18589L), tole(0x06b6b51fL), tole(0x9fbfe4a5L), tole(0xe8b8d433L),
439 tole(0x7807c9a2L), tole(0x0f00f934L), tole(0x9609a88eL), tole(0xe10e9818L),
440 tole(0x7f6a0dbbL), tole(0x086d3d2dL), tole(0x91646c97L), tole(0xe6635c01L),
441 tole(0x6b6b51f4L), tole(0x1c6c6162L), tole(0x856530d8L), tole(0xf262004eL),
442 tole(0x6c0695edL), tole(0x1b01a57bL), tole(0x8208f4c1L), tole(0xf50fc457L),
443 tole(0x65b0d9c6L), tole(0x12b7e950L), tole(0x8bbeb8eaL), tole(0xfcb9887cL),
444 tole(0x62dd1ddfL), tole(0x15da2d49L), tole(0x8cd37cf3L), tole(0xfbd44c65L),
445 tole(0x4db26158L), tole(0x3ab551ceL), tole(0xa3bc0074L), tole(0xd4bb30e2L),
446 tole(0x4adfa541L), tole(0x3dd895d7L), tole(0xa4d1c46dL), tole(0xd3d6f4fbL),
447 tole(0x4369e96aL), tole(0x346ed9fcL), tole(0xad678846L), tole(0xda60b8d0L),
448 tole(0x44042d73L), tole(0x33031de5L), tole(0xaa0a4c5fL), tole(0xdd0d7cc9L),
449 tole(0x5005713cL), tole(0x270241aaL), tole(0xbe0b1010L), tole(0xc90c2086L),
450 tole(0x5768b525L), tole(0x206f85b3L), tole(0xb966d409L), tole(0xce61e49fL),
451 tole(0x5edef90eL), tole(0x29d9c998L), tole(0xb0d09822L), tole(0xc7d7a8b4L),
452 tole(0x59b33d17L), tole(0x2eb40d81L), tole(0xb7bd5c3bL), tole(0xc0ba6cadL),
453 tole(0xedb88320L), tole(0x9abfb3b6L), tole(0x03b6e20cL), tole(0x74b1d29aL),
454 tole(0xead54739L), tole(0x9dd277afL), tole(0x04db2615L), tole(0x73dc1683L),
455 tole(0xe3630b12L), tole(0x94643b84L), tole(0x0d6d6a3eL), tole(0x7a6a5aa8L),
456 tole(0xe40ecf0bL), tole(0x9309ff9dL), tole(0x0a00ae27L), tole(0x7d079eb1L),
457 tole(0xf00f9344L), tole(0x8708a3d2L), tole(0x1e01f268L), tole(0x6906c2feL),
458 tole(0xf762575dL), tole(0x806567cbL), tole(0x196c3671L), tole(0x6e6b06e7L),
459 tole(0xfed41b76L), tole(0x89d32be0L), tole(0x10da7a5aL), tole(0x67dd4accL),
460 tole(0xf9b9df6fL), tole(0x8ebeeff9L), tole(0x17b7be43L), tole(0x60b08ed5L),
461 tole(0xd6d6a3e8L), tole(0xa1d1937eL), tole(0x38d8c2c4L), tole(0x4fdff252L),
462 tole(0xd1bb67f1L), tole(0xa6bc5767L), tole(0x3fb506ddL), tole(0x48b2364bL),
463 tole(0xd80d2bdaL), tole(0xaf0a1b4cL), tole(0x36034af6L), tole(0x41047a60L),
464 tole(0xdf60efc3L), tole(0xa867df55L), tole(0x316e8eefL), tole(0x4669be79L),
465 tole(0xcb61b38cL), tole(0xbc66831aL), tole(0x256fd2a0L), tole(0x5268e236L),
466 tole(0xcc0c7795L), tole(0xbb0b4703L), tole(0x220216b9L), tole(0x5505262fL),
467 tole(0xc5ba3bbeL), tole(0xb2bd0b28L), tole(0x2bb45a92L), tole(0x5cb36a04L),
468 tole(0xc2d7ffa7L), tole(0xb5d0cf31L), tole(0x2cd99e8bL), tole(0x5bdeae1dL),
469 tole(0x9b64c2b0L), tole(0xec63f226L), tole(0x756aa39cL), tole(0x026d930aL),
470 tole(0x9c0906a9L), tole(0xeb0e363fL), tole(0x72076785L), tole(0x05005713L),
471 tole(0x95bf4a82L), tole(0xe2b87a14L), tole(0x7bb12baeL), tole(0x0cb61b38L),
472 tole(0x92d28e9bL), tole(0xe5d5be0dL), tole(0x7cdcefb7L), tole(0x0bdbdf21L),
473 tole(0x86d3d2d4L), tole(0xf1d4e242L), tole(0x68ddb3f8L), tole(0x1fda836eL),
474 tole(0x81be16cdL), tole(0xf6b9265bL), tole(0x6fb077e1L), tole(0x18b74777L),
475 tole(0x88085ae6L), tole(0xff0f6a70L), tole(0x66063bcaL), tole(0x11010b5cL),
476 tole(0x8f659effL), tole(0xf862ae69L), tole(0x616bffd3L), tole(0x166ccf45L),
477 tole(0xa00ae278L), tole(0xd70dd2eeL), tole(0x4e048354L), tole(0x3903b3c2L),
478 tole(0xa7672661L), tole(0xd06016f7L), tole(0x4969474dL), tole(0x3e6e77dbL),
479 tole(0xaed16a4aL), tole(0xd9d65adcL), tole(0x40df0b66L), tole(0x37d83bf0L),
480 tole(0xa9bcae53L), tole(0xdebb9ec5L), tole(0x47b2cf7fL), tole(0x30b5ffe9L),
481 tole(0xbdbdf21cL), tole(0xcabac28aL), tole(0x53b39330L), tole(0x24b4a3a6L),
482 tole(0xbad03605L), tole(0xcdd70693L), tole(0x54de5729L), tole(0x23d967bfL),
483 tole(0xb3667a2eL), tole(0xc4614ab8L), tole(0x5d681b02L), tole(0x2a6f2b94L),
484 tole(0xb40bbe37L), tole(0xc30c8ea1L), tole(0x5a05df1bL), tole(0x2d02ef8dL)
485 };
486
487 #define DO_CRC(x) crc = tab[ (crc ^ (x)) & 255 ] ^ (crc>>8)
crc32_le(unsigned int crc,unsigned char * p,unsigned int len)488 static unsigned int crc32_le(unsigned int crc, unsigned char *p, unsigned int len)
489 {
490 unsigned int *b = (unsigned int *)p;
491 unsigned int *tab = crc32table_le;
492 crc = crc ^ 0xFFFFFFFF;
493 if ((((long)b) & 3 && len)) {
494 do {
495 unsigned char *p = (unsigned char *)b;
496 DO_CRC(*p++);
497 b = (unsigned int *)p;
498 } while ((--len) && ((long)b) & 3 );
499 }
500 if ((len >= 4)) {
501 unsigned int save_len = len & 3;
502 len = len >> 2;
503 --b;
504 do {
505 crc ^= *++b;
506 DO_CRC(0);
507 DO_CRC(0);
508 DO_CRC(0);
509 DO_CRC(0);
510 } while (--len);
511 b++;
512 len = save_len;
513 }
514 if (len) {
515 do {
516 unsigned char *p = (unsigned char *)b;
517 DO_CRC(*p++);
518 b = (unsigned int *)p;
519 } while (--len);
520 }
521 crc = crc ^ 0xFFFFFFFF;
522 return crc;
523
524 }
525
create_gpt_buffer(u8 * gpt,PSTRUCT_PARAM_ITEM p_param,int param_len,PSTRUCT_CONFIG_ITEM p_config,int config_len,u64 diskSectors)526 static void create_gpt_buffer(u8 *gpt, PSTRUCT_PARAM_ITEM p_param, int param_len, PSTRUCT_CONFIG_ITEM p_config, int config_len, u64 diskSectors)
527 {
528 legacy_mbr *mbr = (legacy_mbr *)gpt;
529 gpt_header *gptHead = (gpt_header *)(gpt + SECTOR_SIZE);
530 gpt_entry *gptEntry = (gpt_entry *)(gpt + 2 * SECTOR_SIZE);
531
532 /*1.protective mbr*/
533 memset(gpt, 0, SECTOR_SIZE);
534 mbr->signature = MSDOS_MBR_SIGNATURE;
535 mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT;
536 mbr->partition_record[0].start_sect = 1;
537 mbr->partition_record[0].nr_sects = (u32) - 1;
538
539 /*2.gpt header*/
540 memset(gpt + SECTOR_SIZE, 0, SECTOR_SIZE);
541 gptHead->signature = cpu_to_le64(GPT_HEADER_SIGNATURE);
542 gptHead->revision = cpu_to_le32(GPT_HEADER_REVISION_V1);
543 gptHead->header_size = cpu_to_le32(sizeof(gpt_header));
544 gptHead->my_lba = cpu_to_le64(1);
545 gptHead->alternate_lba = cpu_to_le64(diskSectors - 1);
546 gptHead->first_usable_lba = cpu_to_le64(34);
547 gptHead->last_usable_lba = cpu_to_le64(diskSectors - 34);
548 gptHead->partition_entry_lba = cpu_to_le64(2);
549 gptHead->num_partition_entries = cpu_to_le32(GPT_ENTRY_NUMBERS);
550 gptHead->sizeof_partition_entry = cpu_to_le32(GPT_ENTRY_SIZE);
551 gptHead->header_crc32 = 0;
552 gptHead->partition_entry_array_crc32 = 0;
553 gen_rand_uuid(gptHead->disk_guid.raw);
554
555 /*3.gpt partition entry*/
556 memset(gpt + 2 * SECTOR_SIZE, 0, 32 * SECTOR_SIZE);
557 for (int i = 0; i < param_len; i++) {
558 if (strcmp(p_param[i].name, "") == 0) {
559 continue;
560 }
561 gen_rand_uuid(gptEntry->partition_type_guid.raw);
562 gen_rand_uuid(gptEntry->unique_partition_guid.raw);
563 gptEntry->starting_lba = cpu_to_le64(p_param[i].offset);
564 gptEntry->ending_lba = cpu_to_le64(gptEntry->starting_lba + p_param[i].size - 1);
565 gptEntry->attributes.raw = 0;
566
567 char partition_name[20] = {0};
568 strcpy(partition_name, p_param[i].name);
569 char *p;
570 if ( (p = strstr(partition_name, ":")) != NULL) {
571 if (strstr(partition_name, "bootable") != NULL) {
572 gptEntry->attributes.raw = PART_PROPERTY_BOOTABLE;
573 }
574 if (strstr(partition_name, "grow") != NULL) {
575 gptEntry->ending_lba = cpu_to_le64(diskSectors - 34);
576 }
577 *p = '\0';
578 strcpy(p_param[i].name, partition_name);
579 }
580
581 for (int j = 0; j < strlen(p_param[i].name); j++)
582 gptEntry->partition_name[j] = p_param[i].name[j];
583 for (int j = 0; j < config_len; j++) {
584 if (strcmp(p_config[j].name, p_param[i].name) == 0) {
585 memcpy(gptEntry->unique_partition_guid.raw, p_config[j].value, 16);
586 break ;
587 }
588 }
589 gptEntry++;
590 }
591
592 gptHead->partition_entry_array_crc32 = cpu_to_le32(crc32_le(0, gpt + 2 * SECTOR_SIZE, GPT_ENTRY_SIZE * GPT_ENTRY_NUMBERS));
593 gptHead->header_crc32 = cpu_to_le32(crc32_le(0, gpt + SECTOR_SIZE, sizeof(gpt_header)));
594
595 }
596
prepare_gpt_backup(u8 * master,u8 * backup)597 static void prepare_gpt_backup(u8 *master, u8 *backup)
598 {
599 gpt_header *gptMasterHead = (gpt_header *)(master + SECTOR_SIZE);
600 gpt_header *gptBackupHead = (gpt_header *)(backup + 32 * SECTOR_SIZE);
601 u32 calc_crc32;
602 u64 val;
603
604 /* recalculate the values for the Backup GPT Header */
605 val = le64_to_cpu(gptMasterHead->my_lba);
606 gptBackupHead->my_lba = gptMasterHead->alternate_lba;
607 gptBackupHead->alternate_lba = cpu_to_le64(val);
608 gptBackupHead->partition_entry_lba = cpu_to_le64(le64_to_cpu(gptMasterHead->last_usable_lba) + 1);
609 gptBackupHead->header_crc32 = 0;
610
611 calc_crc32 = crc32_le(0, (unsigned char *)gptBackupHead, le32_to_cpu(gptBackupHead->header_size));
612 gptBackupHead->header_crc32 = cpu_to_le32(calc_crc32);
613 }
614
flash_register_partition_data(PSTRUCT_PARAM_ITEM p_param_item,long long * p_gpt_backup_offset)615 int flash_register_partition_data(PSTRUCT_PARAM_ITEM p_param_item, long long *p_gpt_backup_offset)
616 {
617 if (p_param_item) {
618 gp_param_item = p_param_item;
619 }
620
621 if (p_gpt_backup_offset) {
622 gp_backup_gpt_offset = p_gpt_backup_offset;
623 }
624
625 return 0;
626 }
627
flash_parameter(char * src_path,void * pupdate_cmd)628 int flash_parameter(char *src_path, void *pupdate_cmd)
629 {
630 LOGI("flash_parameter start src_path [%s].\n", src_path);
631 PUPDATE_CMD pcmd = (PUPDATE_CMD)pupdate_cmd;
632
633 unsigned int m_uiParamFileSize = pcmd->size;
634
635 if (m_uiParamFileSize % SECTOR_SIZE != 0) {
636 m_uiParamFileSize = (m_uiParamFileSize / SECTOR_SIZE + 1) * SECTOR_SIZE;
637 }
638
639 // 1. 读取parameter 数据
640 unsigned char data_buf[m_uiParamFileSize];
641 memset(data_buf, 0, m_uiParamFileSize);
642 int fd_src = open(src_path, O_RDONLY);
643 if (fd_src < 0) {
644 LOGE("Can't open %s, %s\n", src_path, strerror(errno));
645 return -2;
646 }
647 if (lseek64(fd_src, pcmd->offset, SEEK_SET) == -1) {
648 LOGE("lseek64 failed (%s:%d), %s.\n", __func__, __LINE__, strerror(errno));
649 close(fd_src);
650 return -2;
651 }
652 if (read(fd_src, data_buf, pcmd->size) != pcmd->size) {
653 close(fd_src);
654 return -2;
655 }
656 close(fd_src);
657
658 // 2. 获取分区大小和uuid
659 STRUCT_PARAM_ITEM param_item[20] = {0};
660 STRUCT_CONFIG_ITEM config_item[10] = {0};
661 getParamFromString((char *)data_buf + 8, param_item);
662 getUuidFromString((char *)data_buf + 8, config_item);
663
664 if (gp_param_item) {
665 memcpy(gp_param_item, param_item, sizeof(param_item) );
666 }
667
668 LOGI("%s-%d: List partitions:\n", __func__, __LINE__);
669 for (int j = 0; j < sizeof(param_item) / sizeof(param_item[0]); j++) {
670 LOGI(" param_item[%d].name [%s]\n", j, param_item[j].name);
671 }
672
673 // 3. 获得flash 的大小,和块数
674 long long block_num;
675 if (getFlashSize(NULL, NULL, &block_num) != 0) {
676 LOGE("getFlashSize error.\n");
677 return -2;
678 }
679
680 LOGI("%s, block_num = %lld.\n", __func__, block_num);
681
682 // 4. 创建gpt 表
683 unsigned char write_buf[SECTOR_SIZE * 67];
684 unsigned char *backup_gpt;
685 backup_gpt = write_buf + 34 * SECTOR_SIZE;
686 memset(write_buf, 0, SECTOR_SIZE * 67);
687 create_gpt_buffer(write_buf, param_item, 20, config_item, 10, block_num);
688 memcpy(backup_gpt, write_buf + 2 * SECTOR_SIZE, 32 * SECTOR_SIZE);
689 memcpy(backup_gpt + 32 * SECTOR_SIZE, write_buf + SECTOR_SIZE, SECTOR_SIZE);
690 prepare_gpt_backup(write_buf, backup_gpt);
691
692 if (gp_backup_gpt_offset) {
693 *gp_backup_gpt_offset = (block_num - 33) * SECTOR_SIZE;
694 }
695
696 //5. 写入主GPT表
697 int fd_dest = open(pcmd->dest_path, O_CREAT | O_RDWR | O_TRUNC, 0644);
698 if (fd_dest < 0) {
699 LOGE("Can't open %s, %s\n", pcmd->dest_path, strerror(errno));
700 return -2;
701 }
702 lseek64(fd_dest, 0, SEEK_SET);
703 if (write(fd_dest, write_buf, 34 * SECTOR_SIZE) != 34 * SECTOR_SIZE) {
704 LOGE("write error %s: (%s:%d).\n", strerror(errno), __func__, __LINE__);
705 close(fd_dest);
706 return -2;
707 }
708 //6. 尾部写入GPT表到文件
709 /*
710 * char gpt_backup_dest_path[100] = {0};
711 * memset(gpt_backup_dest_path, 0, sizeof(gpt_backup_dest_path)/sizeof(gpt_backup_dest_path[0]));
712 * memcpy(gpt_backup_dest_path, pcmd->dest_path, strlen(pcmd->dest_path));
713 * dirname(gpt_backup_dest_path);
714 * sprintf(gpt_backup_dest_path, "%s/%s", gpt_backup_dest_path, GPT_BACKUP_FILE_NAME);
715 */
716
717 #if 0
718 int fd_backup = open(gpt_backup_dest_path, O_CREAT | O_RDWR | O_TRUNC, 0644);
719 if (fd_backup < 0) {
720 LOGE("Can't open %s, %s\n", gpt_backup_dest_path, strerror(errno));
721 return -2;
722 }
723
724 if (write(fd_backup, backup_gpt, 33 * SECTOR_SIZE) != 33 * SECTOR_SIZE) {
725 LOGE("write error %s: (%s:%d).\n", strerror(errno), __func__, __LINE__);
726 close(fd_backup);
727 return -2;
728 }
729 close(fd_backup);
730 #endif
731 close(fd_dest);
732 sync();
733 return 0;
734 }
735
736
flash_bootloader(char * src_path,void * pupdate_cmd)737 int flash_bootloader(char *src_path, void *pupdate_cmd)
738 {
739 PUPDATE_CMD pcmd = (PUPDATE_CMD)pupdate_cmd;
740
741 if (isMtdDevice()) {
742 // bootrom read IDBlock from the offset which is equal to block size for Nand Flash
743 size_t block_size = 0;
744 if (getFlashInfo(NULL, &block_size, NULL) != 0) {
745 LOGE("%s-%d: get mtd info error\n", __func__, __LINE__);
746 return false;
747 }
748 pcmd->flash_offset = block_size;
749 } else {
750 // bootrom read IDBlock from the offset (32KB + 512KB * n <n=0,1,2,3...>) for eMMC
751 pcmd->flash_offset = 32 * 1024;
752 }
753
754 // 1. 读取bootloader
755 unsigned char data_buf[pcmd->size];
756 memset(data_buf, 0, pcmd->size);
757 int fd_src = open(src_path, O_RDONLY);
758 if (fd_src < 0) {
759 LOGE("Can't open %s, %s\n", src_path, strerror(errno));
760 return -2;
761 }
762 if (lseek64(fd_src, pcmd->offset, SEEK_SET) == -1) {
763 LOGE("(%s:%d) lseek64 failed: %s.\n", __func__, __LINE__, strerror(errno));
764 close(fd_src);
765 return -2;
766 }
767 if (read(fd_src, data_buf, pcmd->size) != pcmd->size) {
768 close(fd_src);
769 LOGE("read error(%s:%d) : %s.\n", __func__, __LINE__, strerror(errno));
770 return -2;
771 }
772 close(fd_src);
773
774 if (!download_loader(data_buf, pcmd->size, pcmd->dest_path)) {
775 LOGE("download_loader error.\n");
776 return -1;
777 }
778
779 return 0;
780 }
781
782