xref: /OK3568_Linux_fs/external/recovery/update_engine/flash_image.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 <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