2 * upgrade-apply-deltafs
4 * Copyright (c) 2017 - 2022 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.
26 #include <sys/types.h>
27 #include <sys/reboot.h>
36 #include <hal/device/hal-board.h>
40 #include "fota_util.h"
41 #include "engine/SS_Common.h"
42 #include "engine/SS_UPI.h"
43 #include "engine/fota_common.h"
44 #include "engine/fota_tar.h"
45 #include "engine/ua_types.h"
48 #define SYSTEM_LOG_DIR "/opt/var/log"
49 #define TEMP_FOLDER "/tmp" // TODO
51 //char ua_slot_mode = 0;
52 int dm_verity_status = DM_VERITY_DISABLED;
54 // TODO: Consider changing all to PATH_MAX
55 static char fota_result[MAX_FILE_PATH];
56 static char fota_cause[MAX_FILE_PATH];
57 static char fota_status_path[MAX_FILE_PATH];
58 static char delta_folder[MAX_FOLDER_PATH];
59 static char delta_path[MAX_FILE_PATH];
60 static char log_folder[MAX_FOLDER_PATH];
61 static char result_folder[MAX_FOLDER_PATH];
62 static char temp_folder[MAX_FOLDER_PATH];
63 static char log_path[MAX_FILE_PATH];
65 static ua_part_info_t s_part_info;
67 static ua_update_cfg_t s_update_cfg;
69 static ua_update_data_t s_update_data;
71 typedef struct temp_opt{
77 static ua_delta_info_t s_delta_info;
79 unsigned int __log_level__ =
80 (LOG_DEBUG | LOG_FLASH | LOG_FILE | LOG_FUNCS | LOG_GUI | LOG_ENGINE | LOG_INFO);
81 FILE *__log_out_file__;
83 static void save_result(int result);
84 static void save_cause(int cause);
86 #define TMP_DIR "/tmp/upgrade"
87 #define PROGRESS_FILE TMP_DIR "/ro_progress"
89 #define HAL_PROGRESS_MIN 40
90 #define HAL_PROGRESS_MAX 80
92 void print_usage(const char *msg)
97 printf("print_usage: upgrade-apply-deltafs --archive delta_dir --dest label --archive-file label.img\n"
98 "delta_dir: directory path where delta.tar file is located\n"
99 "label: label of the partition to be updated\n"
100 "label.img: name of the file inside of delta that is to be used during upgrade\n"
104 void print_error_code(int err)
106 char msg[]="upgrade-apply-deltafs error:";
108 case UPI_CONFIG_ERROR:
109 printf("%s config error.\n", msg);
111 case UPI_DELTA_PATH_ERROR:
112 printf("%s delta path error.\n", msg);
114 case UPI_DELTA_PATH_LENGTH_ERROR:
115 printf("%s delta path length error.\n", msg);
117 case UPI_VERSION_ERROR:
118 printf("%s version error.\n", msg);
120 case UPI_VERIFY_ERROR:
121 printf("%s verify error.\n", msg);
123 case UPI_UPDATE_ERROR:
124 printf("%s update error.\n", msg);
126 case UPI_INVALID_PARAM_ERROR:
127 printf("%s invalid parameter error.\n", msg);
129 case UPI_DELTACOUNT_ERROR:
130 printf("%s delta count error.\n", msg);
132 case UPI_PARTINFO_ERROR:
133 printf("%s partition information error.\n", msg);
136 printf("upgrade-apply-deltafs unable to determine error code: %d\n", err);
140 void fota_gui_update_progress(int percent)
147 ret = stat(TMP_DIR, &s);
149 // TMP_DIR exists but it is not directory
150 if (!S_ISDIR(s.st_mode))
153 goto update_progress;
154 } else if (errno == ENOENT) // TMP_DIR not exists
157 LOG("stat failed : %m\n");
162 ret = remove(TMP_DIR);
164 LOG("remove failed : %m\n");
169 ret = mkdir(TMP_DIR, 0755);
171 LOG("mkdir failed : %m\n");
176 fd = creat(PROGRESS_FILE, 0644);
178 LOG("creat failed : %m\n");
182 ret = dprintf(fd, "%d\n", percent);
183 if (close(fd) != 0) {
184 LOG("close failed : %m\n");
188 LOG("write failed (%d) : %m\n", ret);
192 LOG("Succeed to write\n");
195 static void set_upgrade_progress(int percent)
197 int relative_precent = HAL_PROGRESS_MIN + ((HAL_PROGRESS_MAX - HAL_PROGRESS_MIN) * percent)/100;
198 if (hal_device_board_set_upgrade_status(relative_precent) < 0) {
199 LOG("set_upgrade_status failed: %d\n", relative_precent);
203 LOG("set_upgrade_status success: %d\n", relative_precent);
206 /*-----------------------------------------------------------------------------
208 ----------------------------------------------------------------------------*/
209 // TODO - remove this mechanism, only makes log less readable
210 void fota_gui_progress(void * pbUserData, unsigned long uPercent)
214 ua_dataSS_t *ua_data = (ua_dataSS_t *)pbUserData;
215 ua_update_data_t *ua_update_data = ua_data->update_data;
217 LOGL(LOG_FUNCS|LOG_GUI, "%s: ++ uPercent(%lu%%), config->weight=%lu\n", __func__,
218 uPercent, (long unsigned int)ua_update_data->weight);
221 percent = ua_update_data->weight_offset + ua_update_data->weight;
223 percent = ua_update_data->weight_offset + (ua_update_data->weight * uPercent / 100);
225 set_upgrade_progress(percent);
227 * re-arrange progress percentage between scout & update
229 * 0 ~ 100 -> from ~ to
231 switch (ua_data->ua_operation) {
236 case UI_OP_SCOUT_UPDATE:
239 to = (dm_verity_status == DM_VERITY_ENABLED) ? 80 : 100;
247 percent = from + ((to - from) * percent / 100);
249 fota_gui_update_progress(percent); /* update progress bar and text */
251 LOGL(LOG_FUNCS|LOG_GUI, "-- uPercent=%lu, Print Percent(%d%%)\n", uPercent, percent);
254 /*-----------------------------------------------------------------------------
256 ----------------------------------------------------------------------------*/
257 int verify_Delta_FS()
260 ua_dataSS_t ua_dataSS;
261 ua_part_info_t *ua_part_info = &s_part_info;
262 ua_update_cfg_t *ua_update_cfg = &s_update_cfg;
263 ua_update_data_t *ua_update_data = &s_update_data;
264 ua_delta_info_t *ua_delta_info = &s_delta_info;
265 ua_dataSS.parti_info = ua_part_info;
266 ua_dataSS.update_cfg = ua_update_cfg;
267 ua_dataSS.update_data = ua_update_data;
268 ua_dataSS.update_delta = ua_delta_info;
269 ua_dataSS.ua_operation = UI_OP_SCOUT;
270 ua_dataSS.ui_progress = fota_gui_progress;
272 if (ua_update_data->ua_delta_path != NULL) {
273 LOG("Verifying %s \n", ua_dataSS.parti_info->ua_parti_name);
274 ret = SS_FSVerifyPartition(&ua_dataSS);
280 /*-----------------------------------------------------------------------------
282 ----------------------------------------------------------------------------*/
283 int update_Delta_FS(unsigned long ui32Operation)
286 ua_dataSS_t ua_dataSS;
287 ua_part_info_t *ua_part_info = &s_part_info;
288 ua_update_cfg_t *ua_update_cfg = &s_update_cfg;
289 ua_update_data_t *ua_update_data = &s_update_data;
290 ua_delta_info_t *ua_delta_info = &s_delta_info;
291 ua_dataSS.parti_info = ua_part_info;
292 ua_dataSS.update_cfg = ua_update_cfg;
293 ua_dataSS.update_data = ua_update_data;
294 ua_dataSS.update_delta = ua_delta_info;
295 ua_dataSS.ua_operation = ui32Operation;
296 ua_dataSS.ui_progress = fota_gui_progress;
298 if (ua_update_data->ua_delta_path != NULL)
299 ret = SS_FSUpdatemain(&ua_dataSS);
304 /*-----------------------------------------------------------------------------
306 ----------------------------------------------------------------------------*/
307 /* set data weight using data size minimum:1 total: 100 */
309 static void set_data_weight(unsigned int total_data_size)
311 LOG("%s entered, total_data_size=%u\n", __func__, total_data_size);
312 s_update_data.weight = 100;
313 LOG("%s leaved\n", __func__);
316 /*-----------------------------------------------------------------------------
317 set_data_weight_offset
318 ----------------------------------------------------------------------------*/
320 static void set_data_weight_offset(void)
322 LOG("%s entered\n", __func__);
323 s_update_data.weight_offset = 0; // not sure what it does, keep it like this for now
324 LOG("s_update_data.weight_offset=%u\n", s_update_data.weight_offset);
325 LOG("%s leaved\n", __func__);
328 /*-----------------------------------------------------------------------------
330 ----------------------------------------------------------------------------*/
332 static void get_time_stamp(void)
337 gettimeofday(&tv, NULL);
338 sec = (int) tv.tv_sec;
339 msec = (int) (tv.tv_usec / 1000);
340 snprintf(ts, sizeof(ts), "%06d.%03d", sec % 100000, msec);
343 /*-----------------------------------------------------------------------------
345 ----------------------------------------------------------------------------*/
349 int cause = 0, item_size = 0;
350 int last_update_status = UP_START_NONE;
351 int update_status = UP_START_NONE;
352 unsigned long ui32Operation = UI_OP_SCOUT;
353 int del_type = 0; // TODO, for clarity
354 char status_path[MAX_FILE_PATH];
355 snprintf(status_path, MAX_FILE_PATH, "%s/%s",s_update_data.ua_delta_folder, SS_UPDATE_STATUS_PATH);
357 item_size = tar_get_item_size(s_update_data.ua_delta_path, s_part_info.ua_subject_name);
359 s_update_data.data_size = (unsigned int)item_size;
361 s_update_data.data_size = 0;
363 LOGL(LOG_DEBUG, "s_update_data.data_size=%lu, ua_delta_path=%s, "
364 "ua_subject_name=%s\n",
365 (long unsigned int)s_update_data.data_size,
366 s_update_data.ua_delta_path,
367 s_part_info.ua_subject_name);
369 if (s_update_data.data_size <= 0) {
370 ret = UPI_DELTACOUNT_ERROR;
375 LOG(" set weight to draw progressive bar.....\n");
376 set_data_weight(s_update_data.data_size);
377 set_data_weight_offset();
379 LOG("s_part_info.ua_parti_name = %s ua_delta_path = %s ua_subject_name=%s\n",
380 s_part_info.ua_parti_name,
381 s_update_data.ua_delta_path,
382 s_part_info.ua_subject_name);
384 if (SS_Get_last_update_status(&last_update_status, &del_type, status_path) == -1)
385 LOG("No last_update_status. Go normal update scenario.\n");
387 LOG("Get last_update_status. Go Power safe update scenario.\n");
389 LOG("last_update_status: [%d], del_type: [%d] \n", last_update_status, del_type);
391 if (last_update_status == UP_START_NONE) {
393 if (s_update_data.data_size > 0) {
395 LOG("[%s] Verify %s ..............................................................\n", ts,
396 s_part_info.ua_parti_name);
398 ret = verify_Delta_FS();
399 LOG("return form verify : %d\n", ret);
402 ret = UPI_VERIFY_ERROR;
403 LOG("%s verify fail\n", s_part_info.ua_parti_name);
411 LOG("[%s] Verify End ..............................................................\n", ts);
414 ui32Operation = UI_OP_SCOUT_UPDATE;
417 if (s_update_data.data_size > 0) {
419 LOG("[%s] Update %s ..............................................................\n", ts,
420 s_part_info.ua_parti_name);
422 SS_Set_last_update_status(update_status, del_type, status_path); // i have to look into what it does
424 ret = update_Delta_FS(ui32Operation);
425 LOG("return form update : %d\n", ret);
428 ret = UPI_UPDATE_ERROR;
429 LOG("%s update fail\n", s_part_info.ua_parti_name);
435 LOG("[%s] Update End ..............................................................\n", ts);
444 /*-----------------------------------------------------------------------------
446 ----------------------------------------------------------------------------*/
449 memset(log_path, 0x00, sizeof(log_path));
450 snprintf(log_path, sizeof(log_path), "%s", LOG_FILE_PATH);
452 __log_out_file__ = fopen(log_path, "w");
453 if (__log_out_file__ == NULL) {
454 perror("file open error\n");
458 LOG("===== log start [%s] =====\n", ts);
461 /*-----------------------------------------------------------------------------
463 ----------------------------------------------------------------------------*/
464 void log_deinit(void)
467 LOG("===== log end [%s] =====\n", ts);
469 if (__log_out_file__) {
470 fclose(__log_out_file__);
471 __log_out_file__ = NULL;
477 /*-----------------------------------------------------------------------------
479 ----------------------------------------------------------------------------*/
480 static void print_error_cause(int error)
483 case E_SS_FSBADDELTA:
484 LOG("Corrupted firmware update package, did not store correctly. Detected, for example, by mismatched CRCs between actual and expected.\n");
486 case E_SS_BAD_PARAMS:
487 LOG("Wrong Firmware Update Package delivered to device based on current device characteristics\n");
489 case E_SS_MALLOC_ERROR:
490 LOG("The update fails because there isn't sufficient memory to update the device.\n");
492 case E_SS_FSSRCBACKUPFAILED:
493 case E_SS_WRITE_ERROR:
494 case E_SS_FSFAILEDTOBACKUPPATCHINFO:
495 case E_SS_FSBADATTRIBUTES:
496 LOG("The update failed because writing data to the device was unsuccessful.\n");
498 case E_SS_FSSRCCURRUPTED:
499 case E_SS_FSSHA_MISMATCH:
500 case E_SS_FSFAILEDTOPARSEDELTACNT:
501 case E_SS_FSFAILEDTOOPENPATCHINFO:
502 case E_SS_FSFAILEDTOPARSEDELTAINFO:
503 LOG("The update failed because data was corrupted during update of device.\n");
506 LOG("another error\n");
512 <Corrupted Firmware Update Package>
513 Corrupted firmware update package, did not store correctly. Detected, for example, by mismatched CRCs between actual and expected.
514 E_RB_PKG_CORRUPTED(0x8000000D)
515 E_RB_PKG_NOT_AUTHORIZED(0x8000000E): not used
517 <Firmware Update Package-Device Mismatch>
518 Wrong Firmware Update Package delivered to device based on current device characteristics
519 E_RB_BAD_PARAMS(0x800000002)
520 E_RB_WRONG_UPI_VER(0x80000011):not used
521 E_RB_WRONG_UPI_UPDATE(0x80000012): not used
522 E_RB_UPDATE_SECTOR_SIG(0x80000013): not used
524 <Failed Firmware Update Package Validation>
525 Failure to positively validate digital signature of firmware update package
526 E_RB_NON_DP_FORMAT_NOT_SUPPORTED(0x8001001A)
527 E_RB_INVALID_DP_HEADER(0x80010025)
528 E_RB_INVALID_DP_WRONG_SIGNATURE(0x80010026)
529 E_RB_INVALID_DP(0x80010027)
531 <Firmware Update Package Not Acceptable>
532 Firmware Update Package is Not Acceptable
533 E_RB_PKG_TOO_SHORT(0x8000000B) not used
534 E_RB_PKG_TOO_LONG(0x8000000C) not used
535 E_RB_PKG_NOT_AUTHORIZED(0x8000000F)
537 <Firmware update fails due to device out of memory>
538 The update fails because there isn\A1\AFt sufficient memory to update the device.
539 E_RB_NOT_ENOUGH_RAM(0x8000001E)
542 /*-----------------------------------------------------------------------------
544 ----------------------------------------------------------------------------*/
545 void save_cause(int cause)
547 char return_char[20];
550 LOG("%s entered, 0x%x\n", __func__, cause);
552 print_error_cause(cause);
554 if ((result_fp = fopen(fota_cause, "w")) == NULL) {
555 LOG("cause file open fail\n");
559 snprintf(return_char, sizeof(return_char), "%x", cause);
560 fwrite(return_char, strlen(return_char), 1, result_fp);
563 LOG("%s leaved!\n", __func__);
566 /*-----------------------------------------------------------------------------
568 ----------------------------------------------------------------------------*/
569 void save_result(int result)
571 char return_char[20];
574 LOG("%s entered, result=0x%x\n", __func__, result);
576 if ((result_fp = fopen(fota_result, "w")) == NULL) {
577 LOG("result file open fail\n");
581 snprintf(return_char, sizeof(return_char), "%x", result);
582 fwrite(return_char, strlen(return_char), 1, result_fp);
585 LOG("%s leaved!\n", __func__);
590 /*-----------------------------------------------------------------------------
592 ----------------------------------------------------------------------------*/
593 int fota_path_init(void)
595 if (strlen(delta_folder) > MAX_FILE_PATH - 15) {
596 LOG("FOTA path is too long\n");
601 s_update_data.ua_delta_path = malloc(MAX_FILE_PATH);
602 if (s_update_data.ua_delta_path == NULL) {
603 LOG("Memory allocation fail\n");
606 snprintf(s_update_data.ua_delta_path, MAX_FILE_PATH, "%s/%s", delta_folder, DEFAULT_DELTA_NAME);
607 snprintf(fota_cause, sizeof(fota_cause), "%s/%s", result_folder, "cause");
608 snprintf(fota_status_path, sizeof(fota_status_path), "%s/%s", result_folder, UP_STATUS_FILE);
610 LOG("s_part_info[UA_%s].ua_delta_path=%s\n",
611 s_part_info.ua_parti_name,
612 s_update_data.ua_delta_path);
617 /*-----------------------------------------------------------------------------
619 ----------------------------------------------------------------------------*/
620 void fota_path_deinit(void)
622 if (s_update_data.ua_delta_path) {
623 free(s_update_data.ua_delta_path);
624 s_update_data.ua_delta_path = NULL;
626 if (s_update_data.ua_temp_path) {
627 free(s_update_data.ua_temp_path);
628 s_update_data.ua_temp_path = NULL;
632 /*-----------------------------------------------------------------------------
633 check_dm_verity_status
634 ----------------------------------------------------------------------------*/
635 int check_dm_verity_status(void)
639 ret = access("/usr/bin/verityctl", F_OK);
641 if (errno == ENOENT) {
642 LOG("dm-verity status : disabled\n");
643 dm_verity_status = DM_VERITY_DISABLED;
646 LOG("access failed with errno: %d\n", errno);
651 LOG("dm-verity status : enabled\n");
652 dm_verity_status = DM_VERITY_ENABLED;
656 /*-----------------------------------------------------------------------------
658 ----------------------------------------------------------------------------*/
659 void remove_temp_files(void)
666 ua_temp_path = s_update_data.ua_temp_path;
667 if (NULL == ua_temp_path)
670 ret = lstat(ua_temp_path, &sbuf);
672 ret = stat(ua_temp_path, &sbuf);
674 LOG("stat failed with return value: %d errno: %d\n", ret, errno);
679 if (S_ISDIR(sbuf.st_mode)) {
680 ret = rmdir(ua_temp_path);
682 LOG("rmdir(%s) failed with return value: %d errno: %d\n", ua_temp_path, ret, errno);
684 ret = unlink(ua_temp_path);
686 LOG("unlink(%s) failed with return value: %d errno: %d\n", ua_temp_path, ret, errno);
690 /*-----------------------------------------------------------------------------
692 ----------------------------------------------------------------------------*/
693 int arg_parse(int argc, char ** argv, temp_opt *my_opt)
696 print_usage("Invalid parameter count");
699 const char * archive = NULL;
700 const char * archive_file = NULL;
701 const char * dest = NULL;
702 const struct option long_options[] = {
703 {"archive", required_argument, NULL, 0 },
704 {"dest", required_argument, NULL, 1 },
705 {"archive-file", required_argument, NULL, 2 },
709 int option = getopt_long(argc, argv, "", long_options, NULL);
714 if (archive != NULL) {
715 print_usage("Parameters repeated");
722 print_usage("Parameters repeated");
728 if (archive_file != NULL) {
729 print_usage("Parameters repeated");
732 archive_file = optarg;
735 print_usage("Invalid parameters");
739 if (archive_file == NULL || dest == NULL || archive == NULL) {
740 print_usage("Wrong parameters");
743 (*my_opt).archive = archive;
744 (*my_opt).dest = dest;
745 (*my_opt).archive_file = archive_file;
750 /*-----------------------------------------------------------------------------
752 ----------------------------------------------------------------------------*/
753 int main(int argc, char **argv)
755 char ver_str[MAX_PATH];
759 if(arg_parse(argc, argv, &my_opt) < 0) {
760 ret = UPI_INVALID_PARAM_ERROR;
764 #if defined(FEATURE_SUPPORT_CAPABILITY)
765 SS_set_feature_support_capability(1);
768 memset(delta_folder, 0x00, sizeof(delta_folder));
769 snprintf(delta_folder, sizeof(delta_folder)-1, "%s", my_opt.archive);
770 snprintf(delta_path, sizeof(delta_path)-1, "%s/%s", delta_folder, DEFAULT_DELTA_NAME);
771 s_update_data.ua_delta_folder = strdup(delta_folder);
773 memset(temp_folder, 0x00, sizeof(temp_folder));
774 snprintf(temp_folder, sizeof(temp_folder)-1, "%s", TEMP_FOLDER);
776 memset(log_folder, 0x00, sizeof(log_folder));
777 snprintf(log_folder, sizeof(log_folder)-1, "%s", SYSTEM_LOG_DIR);
779 memcpy(result_folder, temp_folder, sizeof(result_folder));
781 snprintf(fota_result, sizeof(fota_result), "%s/%s", result_folder, "result");
785 if (check_dm_verity_status() < 0) { // to be removed
786 LOG("check_dm_verity_status fail\n");
787 ret = UPI_CONFIG_ERROR;
791 s_part_info.ua_parti_name = my_opt.dest;
792 s_part_info.ua_subject_name = my_opt.archive_file;
793 s_update_cfg.source_img_size = 0; // TODO lets see if 0 will work
795 /* load block device number at run-time */
797 ret = fota_path_init();
799 ret = UPI_DELTA_PATH_LENGTH_ERROR;
802 LOG("<<<<<<<<<<< log_init >>>>>>>>>>>>\n");
804 /* UPI version check */
805 if (S_SS_SUCCESS == SS_GetUPIVersion((unsigned char*)ver_str)) {
806 LOG("<<<<<<<<< TOTA Update Agent %s >>>>>>>>>>>>\n", ver_str);
808 LOG("[SS_GetUPIVersion fail] \n");
809 ret = UPI_VERSION_ERROR;
812 /* Main Update Routine : Scout & Update */
814 LOG("[update_all ret=%d]\n", ret);
817 LOG("Result=%d\n", ret);
819 //remove_temp_files(); // TOTA
821 print_error_code(ret);
824 /* Before initialize fota path */
825 case UPI_INVALID_PARAM_ERROR:
826 case UPI_DELTA_PATH_ERROR:
827 case UPI_CONFIG_ERROR:
828 case UPI_PARTINFO_ERROR:
829 case UPI_DELTA_PATH_LENGTH_ERROR:
833 /* After initialize fota path */
834 case UPI_VERSION_ERROR:
835 case UPI_DELTACOUNT_ERROR:
836 case UPI_VERIFY_ERROR:
837 case UPI_UPDATE_ERROR:
845 /* Preserve log file for debugging */
849 LOG("!!! Not expected ret (= %d)\n", ret);
852 if(s_part_info.ua_parti_name) free(s_part_info.ua_parti_name);
853 if(s_part_info.ua_subject_name) free(s_part_info.ua_subject_name);