4 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
25 #include <sys/statfs.h>
26 #include <sys/types.h>
31 #include "SS_PatchDelta.h"
32 #include "fota_common.h"
33 #include "SS_Engine_Errors.h"
35 extern void *SS_Malloc(unsigned int size);
38 unsigned char *buffer;
43 ssize_t ss_memorySink(unsigned char *data, ssize_t len, void *token)
45 MemorySinkInfo *msi = (MemorySinkInfo *) token;
46 if (msi->size - msi->pos < len)
48 memcpy(msi->buffer + msi->pos, data, len);
53 ssize_t ss_fileSink(unsigned char *data, ssize_t len, void *token)
55 int ss_fd = *(int *)token;
59 while (done < (ssize_t) len) {
60 wrote = write(ss_fd, data + done, len - done);
62 if (errno == EINTR || errno == EAGAIN)
63 continue; // try again
64 strerror_r(errno, buf, sizeof(buf));
65 LOGE("error writing %d bytes: %s\n", (int)(len - done), buf);
73 // Take a string 'str' of 40 hex digits and parse it into the 20
74 // byte array 'digest'. 'str' may contain only the digest or be of
75 // the form "<digest>:<anything>". Return 0 on success, -1 on any
77 int ParseSha1(const char *str, uint8_t * digest)
82 for (i = 0; i < SHA_DIGEST_SIZE * 2; ++i, ++ps) {
84 if (*ps >= '0' && *ps <= '9')
86 else if (*ps >= 'a' && *ps <= 'f')
87 digit = *ps - 'a' + 10;
88 else if (*ps >= 'A' && *ps <= 'F')
89 digit = *ps - 'A' + 10;
104 //Function to find the start of gzipped part in compressed kernel
105 int getOffset(char *zimage_path)
107 char gzip_header[] = { 31, -117, 8 }; //header value for gzip which needs to be checked
108 char buf[4] = { 0, };
109 int offset = 0;//wgid:14074
111 FILE *f = fopen(zimage_path, "r");
113 LOGE("Fopen failed for path %s\n", zimage_path);
114 SS_SetUpgradeState(E_SS_OPENFILE_ONLYR);
117 fseek(f, 0, SEEK_SET);
118 while (fread(buf, 1, 3, f) > 0) {
119 if (gzip_header[0] == buf[0] && gzip_header[1] == buf[1] && gzip_header[2] == buf[2]) {
120 LOGL(LOG_SSENGINE, "match for %d %d %d found at %d\n", buf[0], buf[1], buf[2], ftell(f) - 3);
123 if (fseek(f, -2, SEEK_CUR) < 0)
124 LOGE("Failed to fseek\n");
127 offset = ftell(f) - 3;
132 int SS_LoadPartition(const char *filename, FileInfo * file)
139 dev = fopen(filename, "rb");
141 strerror_r(errno, buf, sizeof(buf));
142 LOGE("failed to open partition \"%s\": %s\n", filename, buf);
149 file->data = SS_Malloc(file->size);
151 read = fread(file->data, 1, file->size, dev);
152 LOGL(LOG_SSENGINE, "Partition size read %d\n", read);
153 sha1_update(&sha_ctx, file->data, read);
157 const uint8_t sha_final[SHA_DIGEST_SIZE] = { 0, };
158 sha1_final(&sha_ctx, (uint32_t *) & sha_final);
159 for (i = 0; i < SHA_DIGEST_SIZE; ++i)
160 file->sha1[i] = sha_final[i];
161 //LOGL(LOG_SSENGINE, "Final SHA of Source (%s)\n", sha_final);
163 file->st.st_mode = 0644;
170 //extern int write_data_to_blkdev(char* dev_name, int blk_start, int blk_cnt, char* data);
172 int SS_LoadFile(const char *filename, FileInfo * file)
177 //LOGL(LOG_SSENGINE,"SS_LoadFile --- [File name %s]\n",filename);
179 if (stat(filename, &file->st) != 0) {
180 strerror_r(errno, buf, sizeof(buf));
181 LOGE("failed to stat \"%s\": %s\n", filename, buf);
185 file->size = file->st.st_size;
186 file->data = SS_Malloc(file->size);
188 strerror_r(errno, buf, sizeof(buf));
189 LOGE("failed to allocate memory for \"%s\": %s\n", filename, buf);
193 FILE *f = fopen(filename, "rb");
195 strerror_r(errno, buf, sizeof(buf));
196 LOGE("failed to open \"%s\": %s\n", filename, buf);
202 ssize_t bytes_read = fread(file->data, 1, file->size, f);
203 if (bytes_read != file->size) {
204 LOGE("short read of \"%s\" (%ld bytes of %ld)\n", filename, (long)bytes_read, (long)file->size);
211 //LOGL(LOG_SSENGINE,"SS_LoadFile --- [bytes_read %d]\n",bytes_read);
212 sha1(file->data, file->size, (uint32_t *) file->sha1);
216 extern int gvalid_session;
217 extern void create_dir(char *pathname, int mode);
220 *********************************************************************************
222 *********************************************************************************
225 * This is used to apply patch for a file during delta FS upgrade
230 * @return 0 - in case of success
231 * 1 - in case of error during patch application
233 *********************************************************************************
236 int SS_UpdateDeltaFS(const char *source_filename, const char *target_filename,
237 const char *source_sha1_str, const char *target_sha1_str, int patch_data_size)
239 uint8_t target_sha1[SHA_DIGEST_SIZE];
244 char *outname = NULL;
248 FileInfo source_file;
249 uint8_t source_sha1[SHA_DIGEST_SIZE] = { 0, };
251 if (ParseSha1(target_sha1_str, target_sha1) != 0) {
252 LOGE("failed to parse tgt-sha1 \"%s\"\n", target_sha1_str);
257 if battery removed in between update gvalid_session becomes 0
258 need to check file integrity in that case
260 if (0 == gvalid_session) {
261 if (ParseSha1(source_sha1_str, source_sha1) != 0) {
262 LOGE("failed to parse tgt-sha1 \"%s\"\n", source_sha1_str);
265 if (SS_LoadFile(source_filename, &source_file) == 0) {
266 if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
267 LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Can be applied\n");
268 if (source_file.data)
269 SS_Free(source_file.data);
270 } else if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
271 LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Already applied\n");
272 if (source_file.data)
273 SS_Free(source_file.data);
276 //Check for backup file SHA
277 SS_Free(source_file.data);
278 source_file.data = NULL;
279 LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Source was currupted, Try loading from backup source\n");
280 if (SS_LoadFile(SS_BACKUP_SOURCE, &source_file) == 0) {
281 if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
282 if (SS_CopyFile(SS_BACKUP_SOURCE, source_filename) != S_SS_SUCCESS) {
283 strerror_r(errno, buf, sizeof(buf));
284 LOGE("copy of backup to \"%s\" failed: %s\n", source_filename, buf);
285 SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
286 if (source_file.data)
287 SS_Free(source_file.data);
291 "SS_UpdateDeltaFS - Patch Can be applied from using backup file as source\n");
293 SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
294 if (source_file.data)
295 SS_Free(source_file.data);
299 SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
300 if (source_file.data)
301 SS_Free(source_file.data);
306 LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Source was deleted, Try loading from backup source\n");
307 if (SS_LoadFile(SS_BACKUP_SOURCE, &source_file) == 0) {
308 if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
310 LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Can be applied from using backup file as source\n");
312 SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
313 if (source_file.data)
314 SS_Free(source_file.data);
318 SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
319 if (source_file.data)
320 SS_Free(source_file.data);
325 //Now proceed wit patch application since patch can be applied
327 int enough_space = 0;
328 size_t free_space = 0;
333 tok = strrchr(source_filename, '/');
336 SS_GetAvailableFreeSpace(source_filename, &free_space);
337 enough_space = (free_space > (256 << 10)) && // 256k (two-block) minimum
338 (free_space > (patch_data_size * 3 / 2)); // 50% margin of error
344 #ifndef ENHANCED_BSDIFF
345 backupsrc = SS_BackupSource(source_filename);
346 if (backupsrc != 0) {
347 LOGE("failed to Backup source File:[%s] \n", source_filename);
348 SS_SetUpgradeState(E_SS_FSSRCBACKUPFAILED);
354 LOGL(LOG_SSENGINE, "For %s: free space %ld bytes; enough %d\n", source_filename, (long)free_space,
358 unlink(source_filename);
360 //LOGL(LOG_SSENGINE, "For %s: target %ld bytes; free space %ld bytes; enough %d\n",
361 // source_filename, (long)patch_data_size, (long)free_space, enough_space);
362 //LOGL(LOG_SSENGINE,"Generate Target Space availabitiy [%d]\n", enough_space);
370 // We write the decoded output to "<tgt-file>.patch".
371 //allocate some extra space to allow for concatinating ".patch" with the name
372 outname = (char *)SS_Malloc(strlen(target_filename) + 10);
375 snprintf(outname, strlen(target_filename) + 10,
376 "%s.patch", target_filename);
378 output = open(outname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
381 char *dir_path = strrchr(outname, '/');
383 // need to create directory as the target may be different from source
384 LOGL(LOG_SSENGINE, "need to create directory [%s]\n", outname);
385 create_dir(outname, 0755);
387 output = open(outname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
389 strerror_r(errno, buf, sizeof(buf));
390 LOGE("failed to open output file %s: %s\n", outname, buf);
401 result = SS_ApplyBsdiff(SS_BACKUP_SOURCE, outname, SS_PATCHFILE_SOURCE, sink, token, &ctx1);
403 result = SS_ApplyBsdiff((char *)source_filename, outname, SS_PATCHFILE_SOURCE, sink, token, &ctx1);
411 LOGE("applying patch failed result : [%d]\n", result);
412 SS_Free(outname);//wgid: 20739
413 SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
416 LOGE("applying patch failed; retrying\n");
417 SS_Free(outname);//wgid: 20739
420 // succeeded; no need to retry
423 } while (retry-- > 0);
424 const uint8_t current_target_sha1[SHA_DIGEST_SIZE] = { 0, };
425 sha1_final(&ctx1, (uint32_t *) & current_target_sha1);
426 if (memcmp(current_target_sha1, target_sha1, SHA_DIGEST_SIZE) != 0) {
427 LOGE("patch did not produce expected sha1\n");
428 SS_SetUpgradeState(E_SS_FSSHA_MISMATCH);
433 // Finally, rename the .patch file to replace the target file.
434 #ifdef ENHANCED_BSDIFF
435 if (SS_rename1(outname, target_filename) != 0) {
436 strerror_r(errno, buf, sizeof(buf));
437 LOGE("rename of .patch to \"%s\" failed: %s\n", target_filename, buf);
438 SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
444 if (rename(outname, target_filename) != 0) {
445 strerror_r(errno, buf, sizeof(buf));
446 LOGE("rename of .patch to \"%s\" failed: %s\n", target_filename, buf);
447 SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
452 //remove source file if target is not same
453 if (strcmp(source_filename, target_filename) != 0)
454 unlink(source_filename);
455 SS_BackupSourceClear();
457 SS_PatchSourceClear();
464 *********************************************************************************
465 * SS_UpdateDeltaKernel
466 *********************************************************************************
469 * This is used to apply patch for kernel delta during delta Image upgrade
474 * @return 0 - in case of success
475 * 1 - in case of error during patch application
477 *********************************************************************************
480 int SS_UpdateDeltaKernel(ua_dataSS_t * ua_dataSS, int (*write_to_blkdev) (char *, int, int, char *))
482 uint8_t target_sha1[SHA_DIGEST_SIZE];
483 uint8_t source_sha1[SHA_DIGEST_SIZE];
484 FileInfo source_file;
485 int result = S_SS_SUCCESS;
486 int blk_cnt, read_count = 0;
489 int use_backup_img = -1;
490 FILE *fp = NULL, *wp = NULL, *kp = NULL;
491 int i = 0, j = 0, file_len = 0;
492 char *magic = NULL, *file_name = NULL, *tok_buf = NULL, *buf = NULL, a = '0';
495 char cmd[1024] = { 0, };
496 char source_filename[MAX_FILE_PATH] = { 0, };
497 char part_filename[MAX_FILE_PATH] = { 0, };
502 char *outname = NULL;
503 //Kernel Parts are created on unpacking kernel which is then used to apply delta
504 char *kernel_parts[] = { "decompression_code",
510 if (ParseSha1(ua_dataSS->update_cfg->target_sha1, target_sha1) != 0) {
511 LOGE("failed to parse tgt-sha1 \"%s\"\n", ua_dataSS->update_cfg->target_sha1);
515 source_file.size = ua_dataSS->update_cfg->soure_img_size;
516 source_file.data = NULL;
517 if (0 == gvalid_session) {
519 if (ParseSha1(ua_dataSS->update_cfg->soure_sha1, source_sha1) != 0) {
520 LOGE("failed to parse Src-sha1 \"%s\"\n", ua_dataSS->update_cfg->soure_sha1);
524 if (SS_LoadPartition(ua_dataSS->parti_info->ua_blk_name, &source_file) == 0) {
525 if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
526 LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Patch Can be applied\n");
528 } else if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
529 LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Patch Already applied\n");
530 SS_Free(source_file.data);
533 SS_Free(source_file.data);
534 source_file.data = NULL;
535 LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Source was currupted, Try loading from backup source\n");
536 if (SS_LoadPartition(SS_BACKUP_SOURCE, &source_file) == 0) {
537 if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
541 "SS_UpdateDeltaIMG - Patch Can be applied from using backup file as source\n");
543 SS_SetUpgradeState(E_SS_IMGSRCCURRUPTED);
544 SS_Free(source_file.data);
550 } else { //in case of kernel delta need to copy kernel data from blk to buffer
551 if (SS_LoadPartition(ua_dataSS->parti_info->ua_blk_name, &source_file) != 0) {
552 SS_SetUpgradeState(E_SS_IMGSRCCURRUPTED);
553 LOGE("Fatal Error : Kernel block is corrupted\n");
557 if (use_backup_img == -1) {
558 backupsrc = SS_BackupSource(ua_dataSS->parti_info->ua_blk_name);
559 if (backupsrc != 0) {
560 LOGE("failed to Backup source File:[%s] \n", ua_dataSS->parti_info->ua_blk_name);
561 SS_Free(source_file.data);
562 SS_SetUpgradeState(E_SS_IMGSRCBACKUPFAILED);
566 //Cleanup workspace and copy helper executables to it before proceeding
567 SS_DeleteFolder(SS_KERNEL_WORKSPACE);
568 create_dir(SS_KERNEL_WORKSPACE, 0755);
569 SS_CopyFile(SS_GZIP_SOURCE, SS_GZIP_TARGET);
570 SS_CopyFile(SS_STAT_SOURCE, SS_STAT_TARGET);
571 SS_CopyFile(SS_DD_SOURCE, SS_DD_TARGET);
573 if (tar_get_item_size(ua_dataSS->update_data->ua_delta_path, SS_KERNEL_UNPACK_SCRIPT) > 0)
574 if (tar_extract_file(ua_dataSS->update_data->ua_delta_path, SS_KERNEL_UNPACK_SCRIPT, SS_KERN_UNPK_SCRIPT_PATH) > 0)
575 LOGL(LOG_SSENGINE, "Extracted %s successfully\n", SS_KERNEL_UNPACK_SCRIPT);
577 LOGE("Error in fn tar_extract_file for item %s", SS_KERNEL_UNPACK_SCRIPT);
578 SS_SetUpgradeState(E_SS_DELTA_IS_CORRUPT);
579 result = E_SS_FAILURE;
582 LOGE("Error size is not positive for item %s", SS_KERNEL_UNPACK_SCRIPT);
583 SS_SetUpgradeState(E_SS_DELTA_IS_CORRUPT);
584 result = E_SS_FAILURE;
587 //Now write the kernel data to the workplace and start applying patch
588 snprintf(source_filename, sizeof(source_filename) - 1, "%s/%s", SS_KERNEL_WORKSPACE, SS_KERNEL_NAME);
589 fp = fopen(source_filename, "w");
591 LOGE("file open error [%s] code [%d]\n", source_filename, errno);
592 result = E_SS_FAILURE;
595 //write source kernel data to workspace
596 read_count = fwrite(source_file.data, 1, source_file.size, fp);
597 if (read_count != source_file.size) {
598 LOGE("file write error read_count = %d for [%s]\n", read_count, source_filename);
599 result = E_SS_FAILURE;
603 fp = NULL;//wgid: 59313
605 //Unpack source kernel
606 int offset = getOffset(source_filename);
608 LOGE("Failed to get offset\n");
609 result = E_SS_FAILURE;
612 snprintf(cmd, sizeof(cmd) - 1, "%s -u %s %s %d", SS_KERN_UNPK_SCRIPT_PATH, SS_KERNEL_WORKSPACE, SS_KERNEL_NAME,
614 int ret = _system_cmd_wait(cmd);
615 LOGL(LOG_SSENGINE, "ret for %s is %d\n", cmd, ret);
617 //open delta file, extract kernel delta parts and apply patch to previously unpacked kernel
618 fp = fopen(SS_PATCHFILE_SOURCE, "r");
620 LOGE("Failed to open kernel delta patch\n");
621 result = E_SS_FAILURE;
624 //read kernel delta header for delta names and size
625 buf = SS_Malloc(SS_KERNEL_DELTA_HEADER);
626 if (!buf) {//wgid: 13099
627 LOGE("Failed to allocate memory\n");
628 result = E_SS_MALLOC_ERROR;
631 ssize_t bytes_read = fread(buf, 1, SS_KERNEL_DELTA_HEADER, fp);
632 if (bytes_read != SS_KERNEL_DELTA_HEADER)
633 LOGL(LOG_SSENGINE, "short read of \"%s\" (%ld bytes of %ld)\n", SS_PATCHFILE_SOURCE, (long)bytes_read, (long)SS_KERNEL_DELTA_HEADER);
634 magic = strtok_r(buf, ":", &saveptr);
635 LOGL(LOG_SSENGINE, "magic: %s\n", magic);
636 tok_buf = strtok_r(NULL, ":", &saveptr);
638 file_num = atoi(tok_buf);
640 //adjust offset to start of data section before proceeding
641 fseek(fp, SS_KERNEL_DELTA_HEADER, SEEK_SET);
643 while (file_num-- > 0) {
644 file_name = strtok_r(NULL, ":", &saveptr);
645 tok_buf = strtok_r(NULL, ":", &saveptr);
647 file_len = atoi(tok_buf);
649 snprintf(source_filename, sizeof(source_filename) - 1, "%s/%s_unpacked/%s", SS_KERNEL_WORKSPACE, SS_KERNEL_NAME,
651 snprintf(part_filename, sizeof(part_filename) - 1, "%s/%s", SS_KERNEL_WORKSPACE, file_name);
652 wp = fopen(part_filename, "w");
659 //apply bspatch to the unpacked kernel parts
662 // We write the decoded output to "<tgt-file>.patch".
663 //allocate some extra space to allow for concatinating ".patch" with the name
664 outname = (char *)SS_Malloc(strlen(source_filename) + 10);
665 if (outname == NULL) {
666 SS_SetUpgradeState(E_SS_MALLOC_ERROR);
667 result = E_SS_FAILURE;
670 snprintf(outname, strlen(source_filename) + 10, "%s.patch",
673 output = open(outname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
675 strerror_r(errno, err_buf, sizeof(err_buf));
676 LOGE("failed to open output file %s: %s\n", outname, err_buf);
677 result = E_SS_FAILURE;
683 result = SS_ApplyBsdiff(source_filename, outname, part_filename, sink, tok, NULL);
684 LOGL(LOG_SSENGINE, "GenerateTarget Output is %d and result is %d\n", output, result);
690 if (result != S_SS_SUCCESS) {
691 LOGE("applying patch failed %s\n", source_filename);
696 result = rename(outname, source_filename);
697 if (result != S_SS_SUCCESS) {
698 LOGE("fatal error %s\n", source_filename);
701 if (file_name && strcmp(file_name, "piggy") == 0) {
702 snprintf(cmd, sizeof(cmd) - 1,
703 "%s/gzip -n -9 -c %s/%s/%s > %s/%s/%s.gz",
704 SS_KERNEL_WORKSPACE, SS_KERNEL_WORKSPACE, SS_KERNEL_UNPACK_DIR, file_name,
705 SS_KERNEL_WORKSPACE, SS_KERNEL_UNPACK_DIR, file_name);
706 result = _system_cmd_wait(cmd);
707 LOGL(LOG_SSENGINE, "ret for %s = %d\n", cmd, result);
708 unlink(source_filename);
710 unlink(part_filename);
712 //open new kernel file and append kernel parts to it in
713 snprintf(source_filename, sizeof(source_filename) - 1, "%s/%s", SS_KERNEL_WORKSPACE, SS_KERNEL_TARGET_NAME);
714 kp = fopen(source_filename, "w");
715 for (i = 0; i < 4; i++) {
716 snprintf(part_filename, sizeof(part_filename) - 1, "%s/%s/%s", SS_KERNEL_WORKSPACE, SS_KERNEL_UNPACK_DIR,
718 wp = fopen(part_filename, "r");
719 fseek(wp, SEEK_SET, SEEK_END);
721 fseek(wp, SEEK_SET, SEEK_SET);
730 unlink(part_filename);
736 SS_Free(source_file.data);
737 source_file.data = NULL;
738 if (SS_LoadFile(source_filename, &source_file) == 0)
739 result = memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE);
740 if (result != S_SS_SUCCESS) {
741 LOGE("patch did not produce expected sha1 \n");
742 SS_SetUpgradeState(E_SS_IMGSHA_MISMATCH);
745 //Considering EMMC partition by deafult
747 blk_cnt = ((ua_dataSS->update_cfg->target_img_size - 1) / SECTOR_SIZE) + 1;
748 result = write_to_blkdev((char *)ua_dataSS->parti_info->ua_blk_name, blk_start, blk_cnt, (char *)source_file.data);
749 if (result != S_SS_SUCCESS) {
750 LOGE("write of patched data to %s failed\n", ua_dataSS->parti_info->ua_blk_name); // All returns should go to CLEAN UP.
751 SS_SetUpgradeState(E_SS_IMGFLASHWRITEFAIL);
756 SS_BackupSourceClear();
757 SS_PatchSourceClear();
758 SS_DeleteFile(SS_KERN_UNPK_SCRIPT_PATH);
759 SS_DeleteFolder(SS_KERNEL_WORKSPACE);
760 SS_Free(source_file.data);
762 SS_Free(outname);//wgid: 20740
763 if (result == S_SS_SUCCESS)
764 LOGL(LOG_SSENGINE, "************* SS_UpdateDeltaKernel SUCCESS *****************\n");
766 LOGL(LOG_SSENGINE, "************* SS_UpdateDeltaKernel FAILED *****************\n");
768 fclose(fp);//wgid:14711
775 *********************************************************************************
777 *********************************************************************************
780 * This is used to apply patch for an image during delta Image upgrade
785 * @return 0 - in case of success
786 * 1 - in case of error during patch application
788 *********************************************************************************
791 int SS_UpdateDeltaIMG(ua_dataSS_t * ua_dataSS, int (*write_to_blkdev) (char *, int, int, char *))
793 uint8_t target_sha1[SHA_DIGEST_SIZE];
794 uint8_t source_sha1[SHA_DIGEST_SIZE];
795 const uint8_t current_target_sha1[SHA_DIGEST_SIZE];
796 FileInfo source_file;
799 int result = S_SS_SUCCESS;
803 int use_backup_img = -1;
806 if (ParseSha1(ua_dataSS->update_cfg->target_sha1, target_sha1) != 0) {
807 LOGE("failed to parse tgt-sha1 \"%s\"\n", ua_dataSS->update_cfg->target_sha1);
811 source_file.size = ua_dataSS->update_cfg->soure_img_size;
812 source_file.data = NULL;
813 if (0 == gvalid_session) {
815 if (ParseSha1(ua_dataSS->update_cfg->soure_sha1, source_sha1) != 0) {
816 LOGE("failed to parse Src-sha1 \"%s\"\n", ua_dataSS->update_cfg->soure_sha1);
820 if (SS_LoadPartition(ua_dataSS->parti_info->ua_blk_name, &source_file) == 0) {
821 if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
822 LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Patch Can be applied\n");
823 SS_Free(source_file.data);
824 } else if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
825 LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Patch Already applied\n");
826 SS_Free(source_file.data);
829 SS_Free(source_file.data);
830 source_file.data = NULL;
831 LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Source was currupted, Try loading from backup source\n");
832 if (SS_LoadPartition(SS_BACKUP_SOURCE, &source_file) == 0) {
833 if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
835 SS_Free(source_file.data);
837 "SS_UpdateDeltaIMG - Patch Can be applied from using backup file as source\n");
839 SS_SetUpgradeState(E_SS_IMGSRCCURRUPTED);
840 SS_Free(source_file.data);
847 if (use_backup_img == -1) {
848 backupsrc = SS_BackupSource(ua_dataSS->parti_info->ua_blk_name);
849 if (backupsrc != 0) {
850 LOGE("failed to Backup source File:[%s] \n", ua_dataSS->parti_info->ua_blk_name);
851 SS_SetUpgradeState(E_SS_IMGSRCBACKUPFAILED);
858 blk_cnt = ((ua_dataSS->update_cfg->target_img_size - 1) / SECTOR_SIZE) + 1;
860 msi.buffer = SS_Malloc(blk_cnt * SECTOR_SIZE);
861 if (msi.buffer == NULL) {
862 LOGE("failed to alloc %ld bytes for output\n", (long)ua_dataSS->update_cfg->target_img_size);
863 SS_SetUpgradeState(E_SS_MALLOC_ERROR);
867 msi.size = ua_dataSS->update_cfg->target_img_size;
868 sink = ss_memorySink;
872 //if souce was corrupted, use backup to apply diff
873 if (use_backup_img == -1)
875 SS_ApplyBsdiff((char *)ua_dataSS->parti_info->ua_blk_name, NULL, SS_PATCHFILE_SOURCE, sink, token, &ctx1);
877 result = SS_ApplyBsdiff(SS_BACKUP_SOURCE, NULL, SS_PATCHFILE_SOURCE, sink, token, &ctx1);
878 if (result != S_SS_SUCCESS) {
879 LOGE("failed to SS_ApplyBsdiff\n");
880 SS_SetUpgradeState(E_SS_IMGRECOVERYWRITEFAILED);
884 sha1_final(&ctx1, (uint32_t *) & current_target_sha1);
885 result = memcmp(current_target_sha1, target_sha1, SHA_DIGEST_SIZE);
886 if (result != S_SS_SUCCESS) {
887 LOGE("patch did not produce expected sha1 \n");
888 SS_SetUpgradeState(E_SS_IMGSHA_MISMATCH);
891 //Considering EMMC partition by deafult
893 if (ua_dataSS->update_cfg->update_type == DELTA_IMG) {
894 blk_cnt = ((ua_dataSS->update_cfg->target_img_size - 1) / SECTOR_SIZE) + 1;
895 result = write_to_blkdev((char *)ua_dataSS->parti_info->ua_blk_name, blk_start, blk_cnt, (char *)msi.buffer);
896 if (result != S_SS_SUCCESS) {
897 LOGE("write of patched data to %s failed\n", ua_dataSS->parti_info->ua_blk_name); // All returns should go to CLEAN UP.
898 SS_SetUpgradeState(E_SS_IMGFLASHWRITEFAIL);
901 } else if (ua_dataSS->update_cfg->update_type == EXTRA && ua_dataSS->update_data->ua_temp_path) {
902 fd = open(ua_dataSS->update_data->ua_temp_path, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
904 strerror_r(errno, buf, sizeof(buf));
905 LOGE("failed to open %s for write: %s\n", ua_dataSS->update_data->ua_temp_path, buf);
906 SS_SetUpgradeState(E_SS_IMGRECOVERYWRITEFAILED);
907 result = E_SS_FAILURE;
910 result = SS_WriteFile(fd, 0, msi.buffer, msi.size);
911 if (result != S_SS_SUCCESS) {
912 LOGE("failed to write\n");
913 SS_SetUpgradeState(E_SS_IMGRECOVERYWRITEFAILED);
918 SS_SetUpgradeState(E_SS_IMGUPDATEFAILED);
919 result = E_SS_FAILURE;
920 LOGE("failed to apply patch - Invalid Update type params \n");
924 SS_BackupSourceClear();
925 SS_PatchSourceClear();
930 if (result == S_SS_SUCCESS)
931 LOGL(LOG_SSENGINE, "************* SS_UpdateDeltaIMG SUCCESS *****************\n");