Add delta.ua - a binary to apply an upgrade of DELTA_FS type.
[platform/core/system/upgrade.git] / src / upgrade-apply-deltafs / ua.c
1 /*
2  * upgrade-apply-deltafs
3  *
4  * Copyright (c) 2017 - 2022 Samsung Electronics Co., Ltd.
5  *
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19 #include <assert.h>
20 #include <limits.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/reboot.h>
28 #include <sys/wait.h>
29 #include <sys/time.h>
30 #include <time.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <getopt.h>
35
36 #include <hal/device/hal-board.h>
37
38 #include "fota_cfg.h"
39 #include "ua.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"
46
47
48 #define SYSTEM_LOG_DIR          "/opt/var/log"
49 #define TEMP_FOLDER         "/tmp" // TODO
50
51 //char ua_slot_mode = 0;
52 int dm_verity_status = DM_VERITY_DISABLED;
53
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];
64
65 static ua_part_info_t s_part_info;
66
67 static ua_update_cfg_t s_update_cfg;
68
69 static ua_update_data_t s_update_data;
70
71 typedef struct temp_opt{
72     char * archive;
73     char * archive_file;
74     char * dest;
75 }temp_opt;
76
77 static ua_delta_info_t s_delta_info;
78
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__;
82
83 static void save_result(int result);
84 static void save_cause(int cause);
85
86 #define TMP_DIR "/tmp/upgrade"
87 #define PROGRESS_FILE TMP_DIR "/ro_progress"
88
89 #define HAL_PROGRESS_MIN 40
90 #define HAL_PROGRESS_MAX 80
91
92 void print_usage(const char *msg)
93 {
94         if (msg) {
95                 printf("%s\n", msg);
96         }
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"
101         );
102 }
103
104 void print_error_code(int err)
105 {
106         char msg[]="upgrade-apply-deltafs error:";
107         switch (err) {
108         case UPI_CONFIG_ERROR:
109                 printf("%s config error.\n", msg);
110                 break;
111         case UPI_DELTA_PATH_ERROR:
112                 printf("%s delta path error.\n", msg);
113                 break;
114         case UPI_DELTA_PATH_LENGTH_ERROR:
115                 printf("%s delta path length error.\n", msg);
116                 break;
117         case UPI_VERSION_ERROR:
118                 printf("%s version error.\n", msg);
119                 break;
120         case UPI_VERIFY_ERROR:
121                 printf("%s verify error.\n", msg);
122                 break;
123         case UPI_UPDATE_ERROR:
124                 printf("%s update error.\n", msg);
125                 break;
126         case UPI_INVALID_PARAM_ERROR:
127                 printf("%s invalid parameter error.\n", msg);
128                 break;
129         case UPI_DELTACOUNT_ERROR:
130                 printf("%s delta count error.\n", msg);
131                 break;
132         case UPI_PARTINFO_ERROR:
133                 printf("%s partition information error.\n", msg);
134                 break;
135         default:
136                 printf("upgrade-apply-deltafs unable to determine error code: %d\n", err);
137         }
138 }
139
140 void fota_gui_update_progress(int percent)
141 {
142         int ret;
143         int fd;
144         struct stat s;
145
146         // Check directory
147         ret = stat(TMP_DIR, &s);
148         if (ret == 0) {
149                 // TMP_DIR exists but it is not directory
150                 if (!S_ISDIR(s.st_mode))
151                         goto remove_file;
152                 else
153                         goto update_progress;
154         } else if (errno == ENOENT)     // TMP_DIR not exists
155                 goto make_directory;
156         else {
157                 LOG("stat failed : %m\n");
158                 return;
159         }
160
161 remove_file:
162         ret = remove(TMP_DIR);
163         if (ret != 0) {
164                 LOG("remove failed : %m\n");
165                 return;
166         }
167
168 make_directory:
169         ret = mkdir(TMP_DIR, 0755);
170         if (ret != 0) {
171                 LOG("mkdir failed : %m\n");
172                 return;
173         }
174
175 update_progress:
176         fd = creat(PROGRESS_FILE, 0644);
177         if (fd < 0) {
178                 LOG("creat failed : %m\n");
179                 return;
180         }
181
182         ret = dprintf(fd, "%d\n", percent);
183         if (close(fd) != 0) {
184                 LOG("close failed : %m\n");
185                 return;
186         }
187         if (ret < 2) {
188                 LOG("write failed (%d) : %m\n", ret);
189                 return;
190         }
191
192         LOG("Succeed to write\n");
193 }
194
195 static void set_upgrade_progress(int percent)
196 {
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);
200                 return;
201         }
202
203         LOG("set_upgrade_status success: %d\n", relative_precent);
204 }
205
206 /*-----------------------------------------------------------------------------
207   fota_gui_progress
208  ----------------------------------------------------------------------------*/
209  // TODO - remove this mechanism, only makes log less readable
210 void fota_gui_progress(void * pbUserData, unsigned long uPercent)
211 {
212         int percent;
213         int from, to;
214         ua_dataSS_t *ua_data = (ua_dataSS_t *)pbUserData;
215         ua_update_data_t *ua_update_data = ua_data->update_data;
216
217         LOGL(LOG_FUNCS|LOG_GUI, "%s: ++ uPercent(%lu%%), config->weight=%lu\n", __func__,
218                 uPercent, (long unsigned int)ua_update_data->weight);
219
220         if (uPercent == 100)
221                 percent = ua_update_data->weight_offset + ua_update_data->weight;
222         else
223                 percent = ua_update_data->weight_offset + (ua_update_data->weight * uPercent / 100);
224
225         set_upgrade_progress(percent);
226         /**
227          * re-arrange progress percentage between scout & update
228          *
229          * 0 ~ 100 -> from ~ to
230          */
231         switch (ua_data->ua_operation) {
232         case UI_OP_SCOUT:
233                 from = 0;
234                 to = 20;
235                 break;
236         case UI_OP_SCOUT_UPDATE:
237         case UI_OP_UPDATE:
238                 from = 20;
239                 to = (dm_verity_status == DM_VERITY_ENABLED) ? 80 : 100;
240                 break;
241         default:
242                 from = 0;
243                 to = 100;
244                 break;
245         }
246
247         percent = from + ((to - from) * percent / 100);
248
249         fota_gui_update_progress(percent);      /* update progress bar and text */
250
251         LOGL(LOG_FUNCS|LOG_GUI, "-- uPercent=%lu, Print Percent(%d%%)\n", uPercent, percent);
252 }
253
254 /*-----------------------------------------------------------------------------
255   verify_Delta_FS
256  ----------------------------------------------------------------------------*/
257 int verify_Delta_FS()
258 {
259         int ret = SUCCESS;
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;
271
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);
275         }
276
277         return ret;
278 }
279
280 /*-----------------------------------------------------------------------------
281   update_Delta_FS
282  ----------------------------------------------------------------------------*/
283 int update_Delta_FS(unsigned long ui32Operation)
284 {
285         int ret = SUCCESS;
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;
297
298         if (ua_update_data->ua_delta_path != NULL)
299                 ret = SS_FSUpdatemain(&ua_dataSS);
300
301         return ret;
302 }
303
304 /*-----------------------------------------------------------------------------
305   set_data_weight
306  ----------------------------------------------------------------------------*/
307 /* set data weight using data size minimum:1 total: 100 */
308 // TODO - remove
309 static void set_data_weight(unsigned int total_data_size)
310 {
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__);
314 }
315
316 /*-----------------------------------------------------------------------------
317   set_data_weight_offset
318  ----------------------------------------------------------------------------*/
319  // TODO - remove
320 static void set_data_weight_offset(void)
321 {
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__);
326 }
327
328 /*-----------------------------------------------------------------------------
329   get_time_stamp
330  ----------------------------------------------------------------------------*/
331 static char ts[256];
332 static void get_time_stamp(void)
333 {
334         struct timeval tv;
335         int sec, msec;
336
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);
341 }
342
343 /*-----------------------------------------------------------------------------
344   update_all
345  ----------------------------------------------------------------------------*/
346 int update_all()
347 {
348         int ret = OK;
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);
356
357         item_size = tar_get_item_size(s_update_data.ua_delta_path, s_part_info.ua_subject_name);
358         if (item_size > 0)
359                 s_update_data.data_size = (unsigned int)item_size;
360         else
361                 s_update_data.data_size = 0;
362
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);
368
369         if (s_update_data.data_size <= 0) {
370                 ret = UPI_DELTACOUNT_ERROR;
371                 sleep(3);
372
373                 goto CleanUp;
374         }
375         LOG(" set weight to draw progressive bar.....\n");
376         set_data_weight(s_update_data.data_size);
377         set_data_weight_offset();
378
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);
383
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");
386         else
387                 LOG("Get last_update_status. Go Power safe update scenario.\n");
388
389         LOG("last_update_status: [%d], del_type: [%d] \n", last_update_status, del_type);
390         /* Verify */
391         if (last_update_status == UP_START_NONE) {
392
393                 if (s_update_data.data_size > 0) {
394                         get_time_stamp();
395                         LOG("[%s] Verify %s ..............................................................\n", ts,
396                                 s_part_info.ua_parti_name);
397
398                         ret = verify_Delta_FS();
399                         LOG("return form verify : %d\n", ret);
400                         if (ret != OK) {
401                                 cause = ret;
402                                 ret = UPI_VERIFY_ERROR;
403                                 LOG("%s verify fail\n", s_part_info.ua_parti_name);
404                                 goto CleanUp;
405                         }
406                 }
407
408         }
409
410         get_time_stamp();
411         LOG("[%s] Verify End ..............................................................\n", ts);
412
413         /* Update */
414         ui32Operation = UI_OP_SCOUT_UPDATE;
415
416
417         if (s_update_data.data_size > 0) {
418                 get_time_stamp();
419                 LOG("[%s] Update %s ..............................................................\n", ts,
420                         s_part_info.ua_parti_name);
421
422                 SS_Set_last_update_status(update_status, del_type, status_path); // i have to look into what it does
423
424                 ret = update_Delta_FS(ui32Operation);
425                 LOG("return form update : %d\n", ret);
426                 if (ret != OK) {
427                         cause = ret;
428                         ret = UPI_UPDATE_ERROR;
429                         LOG("%s update fail\n", s_part_info.ua_parti_name);
430                         goto CleanUp;
431                 }
432         }
433
434         get_time_stamp();
435         LOG("[%s] Update End ..............................................................\n", ts);
436
437  CleanUp:
438         if (ret != OK)
439                 save_cause(cause);
440
441         return ret;
442 }
443
444 /*-----------------------------------------------------------------------------
445   log_init
446  ----------------------------------------------------------------------------*/
447 void log_init(void)
448 {
449         memset(log_path, 0x00, sizeof(log_path));
450         snprintf(log_path, sizeof(log_path), "%s", LOG_FILE_PATH);
451
452         __log_out_file__ = fopen(log_path, "w");
453         if (__log_out_file__ == NULL) {
454                 perror("file open error\n");
455                 return;
456         }
457         get_time_stamp();
458         LOG("===== log start [%s] =====\n", ts);
459 }
460
461 /*-----------------------------------------------------------------------------
462   log_deinit
463  ----------------------------------------------------------------------------*/
464 void log_deinit(void)
465 {
466         get_time_stamp();
467         LOG("===== log end [%s] =====\n", ts);
468
469         if (__log_out_file__) {
470                 fclose(__log_out_file__);
471                 __log_out_file__ = NULL;
472         }
473
474         sync();
475 }
476
477 /*-----------------------------------------------------------------------------
478   print_error_cause
479  ----------------------------------------------------------------------------*/
480 static void print_error_cause(int error)
481 {
482         switch (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");
485                 break;
486         case E_SS_BAD_PARAMS:
487                 LOG("Wrong Firmware Update Package delivered to device based on current device characteristics\n");
488                 break;
489         case E_SS_MALLOC_ERROR:
490                 LOG("The update fails because there isn't sufficient memory to update the device.\n");
491                 break;
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");
497                 break;
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");
504                 break;
505         default:
506                 LOG("another error\n");
507                 break;
508         }
509 }
510
511 /*
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
516
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
523
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)
530
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)
536
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)
540 */
541
542 /*-----------------------------------------------------------------------------
543   save_cause
544  ----------------------------------------------------------------------------*/
545 void save_cause(int cause)
546 {
547         char return_char[20];
548         FILE *result_fp;
549
550         LOG("%s entered, 0x%x\n", __func__, cause);
551
552         print_error_cause(cause);
553
554         if ((result_fp = fopen(fota_cause, "w")) == NULL) {
555                 LOG("cause file open fail\n");
556                 return;
557         }
558
559         snprintf(return_char, sizeof(return_char), "%x", cause);
560         fwrite(return_char, strlen(return_char), 1, result_fp);
561         fclose(result_fp);
562
563         LOG("%s leaved!\n", __func__);
564 }
565
566 /*-----------------------------------------------------------------------------
567   save_result
568  ----------------------------------------------------------------------------*/
569 void save_result(int result)
570 {
571         char return_char[20];
572         FILE *result_fp;
573
574         LOG("%s entered, result=0x%x\n", __func__, result);
575
576         if ((result_fp = fopen(fota_result, "w")) == NULL) {
577                 LOG("result file open fail\n");
578                 return;
579         }
580
581         snprintf(return_char, sizeof(return_char), "%x", result);
582         fwrite(return_char, strlen(return_char), 1, result_fp);
583         fclose(result_fp);
584
585         LOG("%s leaved!\n", __func__);
586
587         return;
588 }
589
590 /*-----------------------------------------------------------------------------
591   fota_path_init
592  ----------------------------------------------------------------------------*/
593 int fota_path_init(void)
594 {
595         if (strlen(delta_folder) > MAX_FILE_PATH - 15) {
596                 LOG("FOTA path is too long\n");
597                 return FAIL;
598         }
599
600
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");
604                 return FAIL;
605         }
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);
609
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);
613
614         return SUCCESS;
615 }
616
617 /*-----------------------------------------------------------------------------
618   fota_path_deinit
619  ----------------------------------------------------------------------------*/
620 void fota_path_deinit(void)
621 {
622         if (s_update_data.ua_delta_path) {
623                 free(s_update_data.ua_delta_path);
624                 s_update_data.ua_delta_path = NULL;
625         }
626         if (s_update_data.ua_temp_path) {
627                 free(s_update_data.ua_temp_path);
628                 s_update_data.ua_temp_path = NULL;
629         }
630 }
631
632 /*-----------------------------------------------------------------------------
633   check_dm_verity_status
634  ----------------------------------------------------------------------------*/
635 int check_dm_verity_status(void)
636 {
637         int ret = 0;
638
639         ret = access("/usr/bin/verityctl", F_OK);
640         if (ret == -1) {
641                 if (errno == ENOENT) {
642                         LOG("dm-verity status : disabled\n");
643                         dm_verity_status = DM_VERITY_DISABLED;
644                         return 0;
645                 } else {
646                         LOG("access failed with errno: %d\n", errno);
647                         return -errno;
648                 }
649         }
650
651         LOG("dm-verity status : enabled\n");
652         dm_verity_status = DM_VERITY_ENABLED;
653         return 0;
654 }
655
656 /*-----------------------------------------------------------------------------
657   remove_temp_files
658  ----------------------------------------------------------------------------*/
659 void remove_temp_files(void)
660 {
661         int ret = 0;
662         char *ua_temp_path;
663         struct stat sbuf;
664
665
666         ua_temp_path = s_update_data.ua_temp_path;
667         if (NULL == ua_temp_path)
668                 return;
669
670         ret = lstat(ua_temp_path, &sbuf);
671         if (ret < 0) {
672                 ret = stat(ua_temp_path, &sbuf);
673                 if (ret < 0) {
674                         LOG("stat failed with return value: %d errno: %d\n", ret, errno);
675                         return;
676                 }
677         }
678
679         if (S_ISDIR(sbuf.st_mode)) {
680                 ret = rmdir(ua_temp_path);
681                 if (ret < 0)
682                         LOG("rmdir(%s) failed with return value: %d errno: %d\n", ua_temp_path, ret, errno);
683         } else {
684                 ret = unlink(ua_temp_path);
685                 if (ret < 0)
686                         LOG("unlink(%s) failed with return value: %d errno: %d\n", ua_temp_path, ret, errno);
687         }
688 }
689
690 /*-----------------------------------------------------------------------------
691   arg_parse
692  ----------------------------------------------------------------------------*/
693 int arg_parse(int argc, char ** argv, temp_opt *my_opt)
694 {
695         if (argc != 7) {
696                 print_usage("Invalid parameter count");
697                 return -1;
698         }
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  },
706                 {0}
707         };
708         while (1) {
709                 int option = getopt_long(argc, argv, "", long_options, NULL);
710                 if (option < 0)
711                         break;
712                 switch (option) {
713                 case 0:
714                         if (archive != NULL) {
715                                 print_usage("Parameters repeated");
716                                 return -1;
717                         }
718                         archive = optarg;
719                         break;
720                 case 1:
721                         if (dest != NULL) {
722                                 print_usage("Parameters repeated");
723                                 return -1;
724                         }
725                         dest = optarg;
726                         break;
727                 case 2:
728                         if (archive_file != NULL) {
729                                 print_usage("Parameters repeated");
730                                 return -1;
731                         }
732                         archive_file = optarg;
733                         break;
734                 default:
735                         print_usage("Invalid parameters");
736                         return -1;
737                 }
738         }
739         if (archive_file == NULL || dest == NULL || archive == NULL) {
740                 print_usage("Wrong parameters");
741                 return -1;
742         }
743         (*my_opt).archive = archive;
744         (*my_opt).dest = dest;
745         (*my_opt).archive_file = archive_file;
746
747         return 0;
748 }
749
750 /*-----------------------------------------------------------------------------
751   main
752  ----------------------------------------------------------------------------*/
753 int main(int argc, char **argv)
754 {
755         char ver_str[MAX_PATH];
756         int ret = FAIL;
757         temp_opt my_opt;
758         log_init();
759         if(arg_parse(argc, argv, &my_opt) < 0) {
760                 ret = UPI_INVALID_PARAM_ERROR;
761                 goto Results;
762         }
763
764 #if defined(FEATURE_SUPPORT_CAPABILITY)
765         SS_set_feature_support_capability(1);
766 #endif
767
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);
772
773         memset(temp_folder, 0x00, sizeof(temp_folder));
774         snprintf(temp_folder, sizeof(temp_folder)-1, "%s", TEMP_FOLDER);
775
776         memset(log_folder, 0x00, sizeof(log_folder));
777         snprintf(log_folder, sizeof(log_folder)-1, "%s", SYSTEM_LOG_DIR);
778
779         memcpy(result_folder, temp_folder, sizeof(result_folder));
780
781         snprintf(fota_result, sizeof(fota_result), "%s/%s", result_folder, "result");
782
783         fota_cfg_str_load();
784
785         if (check_dm_verity_status() < 0) { // to be removed
786                 LOG("check_dm_verity_status fail\n");
787                 ret = UPI_CONFIG_ERROR;
788                 goto Results;
789         }
790
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
794
795         /* load block device number at run-time */
796
797         ret = fota_path_init();
798         if (ret == FAIL) {
799                 ret = UPI_DELTA_PATH_LENGTH_ERROR;
800                 goto Results;
801         }
802         LOG("<<<<<<<<<<< log_init >>>>>>>>>>>>\n");
803
804         /* UPI version check */
805         if (S_SS_SUCCESS == SS_GetUPIVersion((unsigned char*)ver_str)) {
806                 LOG("<<<<<<<<< TOTA Update Agent %s >>>>>>>>>>>>\n", ver_str);
807         } else {
808                 LOG("[SS_GetUPIVersion fail] \n");
809                 ret = UPI_VERSION_ERROR;
810                 goto Results;
811         }
812         /* Main Update Routine : Scout & Update */
813         ret = update_all();
814         LOG("[update_all ret=%d]\n", ret);
815
816  Results:
817         LOG("Result=%d\n", ret);
818         save_result(ret);
819         //remove_temp_files(); // TOTA
820         if (ret != SUCCESS)
821                 print_error_code(ret);
822
823         switch (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:
830                 log_deinit();
831                 _exit_stdio();
832                 return -1;
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:
838                 fota_path_deinit();
839                 log_deinit();
840                 _exit_stdio();
841                 return -1;
842         case SUCCESS:
843                 fota_path_deinit();
844                 log_deinit();
845                 /* Preserve log file for debugging */
846                 _exit_stdio();
847                 return 0;
848         default:
849                 LOG("!!! Not expected ret (= %d)\n", ret);
850         }
851
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);
854
855         _exit_stdio();
856         return -1;
857 }