| // 2017-07-31 carota Rock FOTA ua porting file |
| |
| |
| #define ROCK_FOTA_SUPPORT |
| |
| #ifdef ROCK_FOTA_SUPPORT |
| |
| |
| #include "iot_rock.h" |
| #include "iot_rock_ipl.h" |
| #include "sha.h" |
| #include <log/log.h> |
| #include <stdarg.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <dlfcn.h> |
| #include <stdint.h> |
| |
| |
| #include <hardware/boot_control.h> |
| #include <hardware/hardware.h> |
| #include <sys/reboot.h> |
| |
| |
| |
| #include "liblog/lynq_deflog.h" |
| #include "mtk_device_wrap.h" |
| #include <include/lynq_uci.h> |
| |
| #define ROCK_DEFAULT_BLOCK_SIZE 0x40000 |
| #define ROCK_RAM_LEN (1024*1024) |
| |
| #define LOG_TAG "LYNQ_FOTA" |
| #define ROCK_BACKUP_LEN ROCK_DEFAULT_BLOCK_SIZE |
| |
| |
| |
| #define FILENAME_SIZE 50 |
| |
| |
| |
| //#define DEV_DELTA "/dev/disk/by-partlabel/delta" |
| #if 0 |
| #define DEV_DELTA "/dev/disk/by-partlabel/delta" |
| #else |
| #define DEV_DELTA "/dev/mtd41" |
| #endif |
| |
| |
| |
| char partition_filename_a[][FILENAME_SIZE] = { |
| {"/dev/disk/by-partlabel/system_a"}, |
| {"/dev/disk/by-partlabel/boot_a"}, |
| {"/dev/disk/by-partlabel/tee_a"}, |
| {"/dev/disk/by-partlabel/md1img_a"}, |
| {"/dev/disk/by-partlabel/md1dsp_a"}, |
| {"/dev/disk/by-partlabel/vbmeta_a"}, |
| {"/dev/disk/by-partlabel/oemapp_a"}, |
| {"/dev/disk/by-partlabel/oemapp2_a"}, |
| {"/dev/disk/by-partlabel/medmcu_a"}, |
| {"/dev/disk/by-partlabel/spm_a"}, |
| {"/dev/disk/by-partlabel/protect_a"}, |
| {"/dev/disk/by-partlabel/mcf1_a"}, |
| {"/dev/disk/by-partlabel/mcf2_a"}, |
| {"/dev/disk/by-partlabel/mcupm_a"}, |
| {"/dev/disk/by-partlabel/sspm_a"}, |
| {"/dev/disk/by-partlabel/dpm_a"}, |
| {"/dev/disk/by-partlabel/pi_img_a"}, |
| {"/dev/disk/by-partlabel/hsm_os_a"}, |
| {"/dev/disk/by-partlabel/bl2_a"}, |
| {"/dev/disk/by-partlabel/bl33_a"} |
| }; |
| |
| |
| char partition_filename_b[][FILENAME_SIZE] = { |
| {"/dev/disk/by-partlabel/system_b"}, |
| {"/dev/disk/by-partlabel/boot_b"}, |
| {"/dev/disk/by-partlabel/tee_b"}, |
| {"/dev/disk/by-partlabel/md1img_b"}, |
| {"/dev/disk/by-partlabel/md1dsp_b"}, |
| {"/dev/disk/by-partlabel/vbmeta_b"}, |
| {"/dev/disk/by-partlabel/oemapp_b"}, |
| {"/dev/disk/by-partlabel/oemapp2_b"}, |
| {"/dev/disk/by-partlabel/medmcu_b"}, |
| {"/dev/disk/by-partlabel/spm_b"}, |
| {"/dev/disk/by-partlabel/protect_b"}, |
| {"/dev/disk/by-partlabel/mcf1_b"}, |
| {"/dev/disk/by-partlabel/mcf2_b"}, |
| {"/dev/disk/by-partlabel/mcupm_b"}, |
| {"/dev/disk/by-partlabel/sspm_b"}, |
| {"/dev/disk/by-partlabel/dpm_b"}, |
| {"/dev/disk/by-partlabel/pi_img_b"}, |
| {"/dev/disk/by-partlabel/hsm_os_b"}, |
| {"/dev/disk/by-partlabel/bl2_b"}, |
| {"/dev/disk/by-partlabel/bl33_b"} |
| }; |
| |
| |
| |
| |
| char partition_filename[][FILENAME_SIZE] = { |
| {"system"}, |
| {"boot"}, |
| {"tee"}, |
| {"md1img"}, |
| {"md1dsp"}, |
| {"vbmeta"}, |
| {"oemapp"}, |
| {"oemapp2"}, |
| {"medmcu"}, |
| {"spm"}, |
| {"protect"}, |
| {"mcf1"}, |
| {"mcf2"}, |
| {"mcupm"}, |
| {"sspm"}, |
| {"dpm"}, |
| {"pi_img"}, |
| {"hsm_os"}, |
| {"bl2"}, |
| {"bl33"} |
| }; |
| //+10 |
| |
| unsigned int delta_head[128]={0}; //512/4 128/2=64 |
| |
| |
| |
| #define FOTA_UCI_MODULE "lynq_fota" |
| #define FOTA_UCI_FILE "lynq_uci" |
| #define FOTA_UCI_ADDR "lynq_fota_addr" |
| #define FOTA_UCI_STATE "lynq_fota_state" |
| |
| #define FILE_UPDATE_STATE "/data/.update_status" |
| #define FILE_UPDATE_FLAG "/tmp/update_flag" |
| #define FILE_FOTA_STATE "/data/.fota_status" |
| |
| #define NAND_PAGE_SIZE 4096 |
| |
| |
| #define BOOTDEV_TYPE_NAND 1 |
| |
| #define BACKUP_ADDR_FLAG 0xffffffff |
| #define FILE_BACKUP "/data/.backup" |
| |
| #define SLOT_A 0 |
| #define SLOT_B 1 |
| |
| #define FULL_HEAD "full-ota" |
| |
| //xf.li@20230822 add for ab rollback start |
| #define DEV_SYSTEM_A "/dev/disk/by-partlabel/system_a" |
| #define DEV_SYSTEM_B "/dev/disk/by-partlabel/system_b" |
| |
| #define DEV_BOOT_A "/dev/disk/by-partlabel/boot_a" |
| #define DEV_BOOT_B "/dev/disk/by-partlabel/boot_b" |
| |
| #define DEV_SPM_A "/dev/disk/by-partlabel/spm_a" |
| #define DEV_SPM_B "/dev/disk/by-partlabel/spm_b" |
| |
| #define DEV_MD1IMG_A "/dev/disk/by-partlabel/md1img_a" |
| #define DEV_MD1IMG_B "/dev/disk/by-partlabel/md1img_b" |
| |
| #define DEV_TEE_A "/dev/disk/by-partlabel/tee_a" |
| #define DEV_TEE_B "/dev/disk/by-partlabel/tee_b" |
| |
| #define DEV_VBMETA_A "/dev/disk/by-partlabel/vbmeta_a" |
| #define DEV_VBMETA_B "/dev/disk/by-partlabel/vbmeta_b" |
| |
| #define DEV_BL2_A "/dev/disk/by-partlabel/bl2_a" |
| #define DEV_BL2_B "/dev/disk/by-partlabel/bl2_b" |
| |
| #define DEV_BL33_A "/dev/disk/by-partlabel/bl33_a" |
| #define DEV_BL33_B "/dev/disk/by-partlabel/bl33_b" |
| |
| #define DEV_MEDMCU_A "/dev/disk/by-partlabel/medmcu_a" |
| #define DEV_MEDMCU_B "/dev/disk/by-partlabel/medmcu_b" |
| |
| #define DEV_OEMAPP_A "/dev/disk/by-partlabel/oemapp_a" |
| #define DEV_OEMAPP_B "/dev/disk/by-partlabel/oemapp_b" |
| |
| #define DEV_OEMAPP2_A "/dev/disk/by-partlabel/oemapp2_a" |
| #define DEV_OEMAPP2_B "/dev/disk/by-partlabel/oemapp2_b" |
| |
| |
| #define DEV_MISC "/dev/disk/by-partlabel/misc" |
| |
| #define BACKUP_UBI_NUM 31 //max ubi number |
| #define MTD_SYSTEM_A 14 |
| #define MTD_SYSTEM_B 15 |
| #define MD5_RETRY_TIME 3 |
| #define MD5_VERFY_ERROR 5 |
| #define MD5_READ_BUFFER_LEN 4*1024 |
| #define FOTA_FIRST 0 |
| #define RECOVER_FIRST 1 |
| int fota_interrupt = 1; |
| //xf.li@20230822 add for ab rollback end |
| |
| |
| //int fd_system_a,fd_system_b,fd_boot_a,fd_boot_b,fd_tee_a,fd_tee_b,fd_bl2,fd_bl33,fd_delta,fd_curr,fd_log,fd_update_status,fd_md1img_a,fd_md1img_b,fd_fota_status,fd_md1dsp_a,fd_md1dsp_b,fd_vbmeta_a,fd_vbmeta_b,fd_oemapp_a,fd_oemapp_b,fd_oemapp2_a,fd_oemapp2_b,fd_medmcu_a,fd_medmcu_b,fd_bl33_a,fd_bl33_b; |
| int fd_delta,fd_curr,fd_log,fd_update_status,fd_fota_status; |
| int fd_write,fd_read; |
| |
| static unsigned int delta_offset = 0; |
| static unsigned int now_patch = 0; |
| unsigned int current_slot = 0; |
| unsigned char rock_debug_buffer[512]; |
| |
| |
| |
| OTA_STATUS fota_status; |
| UPDATE_INFO up_info; |
| |
| |
| extern const hw_module_t HAL_MODULE_INFO_SYM; |
| boot_control_module_t* module; |
| |
| static void lynq_init_wake_lock_func(void); |
| static void lynq_fota_grab_artial_wake_lock(void); |
| static void lynq_fota_release_wake_lock(void); |
| int check(int sys_size); |
| int check_cpu(); |
| |
| static const char hex_chars[] = "0123456789abcdef"; |
| |
| /** |
| * @brief The following is the wake up |
| * start |
| */ |
| |
| #define ANDROID_WAKE_LOCK_NAME "fota-interface" |
| |
| void *dlHandle_wakelock; |
| |
| enum { |
| PARTIAL_WAKE_LOCK = 1, // the cpu stays on, but the screen is off |
| FULL_WAKE_LOCK = 2 // the screen is also on |
| }; |
| |
| // while you have a lock held, the device will stay on at least at the |
| // level you request. |
| |
| int (*acquire_wake_lock)(int lock, const char* id); |
| int (*release_wake_lock)(const char* id); |
| |
| void convert_hex(unsigned char *sha, unsigned char *shastr) |
| { |
| int i; |
| int j = 0; |
| unsigned int c; |
| |
| for (i = 0; i < 20; i++) { |
| c = (sha[i] >> 4) & 0x0f; |
| shastr[j++] = hex_chars[c]; |
| shastr[j++] = hex_chars[sha[i] & 0x0f]; |
| } |
| shastr[40] = '\0'; |
| } |
| |
| |
| |
| |
| int rock_mismatch(void* ctx, unsigned char* buf, unsigned int start, unsigned int size, |
| unsigned int source_hash,unsigned int target_hash) { |
| |
| return 0; |
| } |
| |
| int rock_fatal(void* ctx, int error_code) { |
| return 0; |
| } |
| |
| void rock_trace(void* ctx, const char* fmt, ...) { |
| |
| va_list ap; |
| memset(rock_debug_buffer,0x0,sizeof(rock_debug_buffer)); |
| va_start (ap, fmt); |
| |
| |
| vsnprintf(rock_debug_buffer,sizeof(rock_debug_buffer),fmt,ap); |
| LYDBGLOG("+[UA]: %s",rock_debug_buffer); |
| |
| |
| va_end (ap); |
| |
| } |
| |
| static int save_fota_status() |
| { |
| int err; |
| fd_fota_status = open(FILE_FOTA_STATE,O_RDWR | O_CREAT,0777); |
| |
| if (fd_fota_status < 0) { |
| err = errno; |
| RLOGD("+[UA]: save_fota_status: Error opening metadata file: %s\n",strerror(errno)); |
| return -err; |
| } |
| |
| write(fd_fota_status, &fota_status,sizeof(fota_status)); |
| sync(); |
| |
| close(fd_fota_status); |
| } |
| |
| static int save_fota_info() |
| { |
| int err; |
| fd_update_status = open(FILE_UPDATE_STATE,O_RDWR); |
| |
| if (fd_update_status < 0) { |
| err = errno; |
| RLOGD("+[UA]: save_fota_status: Error opening metadata file: %s\n",strerror(errno)); |
| return -err; |
| } |
| |
| write(fd_update_status, &up_info, sizeof(fota_status)); |
| sync(); |
| close(fd_update_status); |
| } |
| |
| |
| |
| void rock_progress(void* ctx, int percent) { |
| int i = 0; |
| static int tmp_percent = -1; |
| rock_trace(ctx, "rock update progress %d\n", percent); |
| |
| if (tmp_percent != percent) { |
| tmp_percent = percent; |
| if (percent > 20) { |
| i = fota_status.ota_run; |
| if (fota_status.update_status[i-1].check_delta != PASS) { |
| fota_status.update_status[i-1].check_delta = PASS; |
| fota_status.update_status[i-1].check_rom= PASS; |
| save_fota_status(); |
| } |
| } |
| } |
| } |
| |
| int rock_process_block(void* ctx, unsigned char* data, unsigned int start, unsigned int size){ |
| //rock_trace(ctx, "rock update progress block %d\n", size); |
| |
| int writen = 0; |
| int ret,err; |
| |
| |
| if (start == BACKUP_ADDR_FLAG) { |
| int fd_backup = open(FILE_BACKUP,O_RDWR | O_CREAT,0777); |
| while (writen < size) { |
| write(fd_backup,data,ROCK_DEFAULT_BLOCK_SIZE); |
| sync(); |
| writen += ROCK_DEFAULT_BLOCK_SIZE; |
| } |
| close(fd_backup); |
| return size; |
| } |
| |
| |
| |
| writen = 0; |
| |
| if (mtk_device_wrap_seek(fd_write, start, SEEK_SET) < 0) { |
| err = errno; |
| rock_trace(ctx, "mtk_device_wrap_seek write\n"); |
| return err; |
| } |
| |
| while (writen < size) { |
| ret = mtk_device_wrap_write(fd_write,data+writen, ROCK_DEFAULT_BLOCK_SIZE); |
| writen += ROCK_DEFAULT_BLOCK_SIZE; |
| } |
| |
| |
| return size; |
| } |
| |
| int rock_write_block(void* ctx, unsigned char* src, unsigned int start, unsigned int size){ |
| |
| #if 0 |
| |
| int writen = 0; |
| int ret,err; |
| |
| |
| if (start == BACKUP_ADDR_FLAG) { |
| int fd_backup = open(FILE_BACKUP,O_RDWR | O_CREAT,0777); |
| while (writen < size) { |
| write(fd_backup,src,ROCK_DEFAULT_BLOCK_SIZE); |
| sync(); |
| writen += ROCK_DEFAULT_BLOCK_SIZE; |
| } |
| close(fd_backup); |
| return size; |
| } |
| |
| writen = 0; |
| |
| if (mtk_device_wrap_seek(fd_curr, start, SEEK_SET) < 0) { |
| err = errno; |
| rock_trace(ctx, "mtk_device_wrap_seek write\n"); |
| return err; |
| } |
| |
| while (writen < size) { |
| ret = mtk_device_wrap_write(fd_curr,src+writen, ROCK_DEFAULT_BLOCK_SIZE); |
| writen += ROCK_DEFAULT_BLOCK_SIZE; |
| } |
| |
| |
| #endif |
| |
| return size; |
| |
| } |
| |
| int rock_read_block(void* ctx, unsigned char* dest, unsigned int start, unsigned int size){ |
| |
| |
| int ret,err; |
| |
| |
| if (start == BACKUP_ADDR_FLAG) { |
| int fd_backup = open(FILE_BACKUP,O_RDONLY); |
| read(fd_backup,dest,size); |
| sync(); |
| close(fd_backup); |
| return size; |
| } |
| |
| |
| |
| if (mtk_device_wrap_seek(fd_read, start, SEEK_SET) < 0) { |
| err = errno; |
| rock_trace(ctx, "mtk_device_wrap_seek read block err\n"); |
| } |
| |
| do { |
| |
| ret = mtk_device_wrap_read(fd_read, dest, size); |
| |
| if (ret == 0) { |
| break; |
| } else if (ret < 0) { |
| if (errno == EINTR) { |
| continue; |
| } |
| err = -errno; |
| rock_trace(ctx,"%s Error reading metadata file\n"); |
| |
| mtk_device_wrap_close(fd_read); |
| |
| return err; |
| } |
| size -= ret; |
| dest += ret; |
| } while(size > 0); |
| |
| |
| return ret; |
| |
| |
| } |
| |
| |
| int rock_read_delta(void* ctx, unsigned char* dest, unsigned int offset, unsigned int size){ |
| |
| int ret = 0,err = 0; |
| |
| |
| if (lseek(fd_delta, offset + delta_offset, SEEK_SET) < 0) { |
| err = -errno; |
| rock_trace(ctx, "mtk_device_wrap_seek df_delta err\n"); |
| return err; |
| } |
| |
| do { |
| |
| ret = read(fd_delta, dest, size); |
| |
| if (ret == 0) { |
| break; |
| } else if (ret < 0) { |
| if (errno == EINTR) { |
| continue; |
| } |
| err = -errno; |
| rock_trace(ctx," Error reading metadata file\n"); |
| |
| close(fd_delta); |
| |
| return err; |
| } |
| size -= ret; |
| dest += ret; |
| } while(size > 0); |
| |
| return ret; |
| |
| } |
| |
| int rock_get_blocksize(void* ctx) { |
| return ROCK_DEFAULT_BLOCK_SIZE; |
| } |
| |
| int rock_read_file(void* ctx, void* name, unsigned char* dest, unsigned int offset, unsigned int size){return 0;} |
| int rock_write_file(void* ctx, void* name, unsigned char* src, unsigned int offset, unsigned int size){return 0;} |
| int rock_delete_file(void* ctx, void* name){return 0;} |
| /* ROCK IPL end */ |
| |
| |
| |
| static int init_dev_fd() |
| { |
| |
| int err; |
| char lynq_fota_addr[64] = {0}; |
| char fota_name[]= "fota.delta"; |
| int n; |
| if(0 != lynq_fota_get_addr_value(lynq_fota_addr)) |
| { |
| return E_ROCK_FOTA_ADDR; |
| } |
| RLOGD("+[UA]: get fota pack addr: %s\n",lynq_fota_addr); |
| fd_delta = open(lynq_fota_addr,O_RDWR); |
| |
| if (fd_delta < 0) { |
| err = errno; |
| RLOGD("+[UA]: Error opening metadata file: %s\n",strerror(errno)); |
| return -err; |
| } |
| |
| fd_update_status = open(FILE_UPDATE_STATE,O_RDWR | O_CREAT,0777); |
| if (fd_update_status < 0) { |
| err = errno; |
| RLOGD("+[UA]: Error opening metadata file: %s\n",strerror(errno)); |
| return -err; |
| } |
| memset(&up_info, 0, sizeof(up_info)); |
| lseek(fd_update_status,0,SEEK_SET); |
| read(fd_update_status,(unsigned char *)&up_info,sizeof(up_info)); |
| close(fd_update_status); |
| return 0; |
| } |
| |
| |
| |
| |
| |
| static int close_dev_fd(int fd) |
| { |
| close(fd); |
| } |
| |
| |
| |
| static int reboot_device() { |
| |
| reboot(RB_AUTOBOOT); |
| |
| while (1) pause(); |
| } |
| |
| |
| |
| int test_write_delta(char *source, char *target) |
| { |
| int fd_source,fd_target,size; |
| |
| char delta_data[ROCK_DEFAULT_BLOCK_SIZE]; |
| |
| fd_source = open(source,O_RDONLY); |
| |
| if (fd_source < 0) { |
| RLOGD("+[UA]: open source error\n"); |
| return 1; |
| } |
| |
| fd_target = mtk_device_wrap_open(target,O_RDWR); |
| |
| if (fd_target < 0) { |
| mtk_device_wrap_close(fd_target); |
| close(fd_source); |
| RLOGD("+[UA]: open target error\n"); |
| return 1; |
| } |
| |
| while(( size = read(fd_source,delta_data,ROCK_DEFAULT_BLOCK_SIZE))>0) { |
| mtk_device_wrap_write(fd_target,delta_data,ROCK_DEFAULT_BLOCK_SIZE); |
| } |
| |
| mtk_device_wrap_close(fd_target); |
| close(fd_source); |
| return 0; |
| } |
| |
| |
| int nand_copyto_nand(char *source, char *target) |
| { |
| int fd_source,fd_target,size; |
| |
| char delta_data[ROCK_DEFAULT_BLOCK_SIZE]; |
| |
| fd_source = mtk_device_wrap_open(source,O_RDONLY); |
| |
| if (fd_source < 0) { |
| RLOGD("+[UA]: open source error\n"); |
| return 1; |
| } |
| |
| fd_target = mtk_device_wrap_open(target,O_RDWR); |
| |
| if (fd_target < 0) { |
| mtk_device_wrap_close(fd_target); |
| mtk_device_wrap_close(fd_source); |
| RLOGD("+[UA]: open target error\n"); |
| return 1; |
| } |
| |
| while(( size = mtk_device_wrap_read(fd_source,delta_data,ROCK_DEFAULT_BLOCK_SIZE))>0) { |
| mtk_device_wrap_write(fd_target,delta_data,ROCK_DEFAULT_BLOCK_SIZE); |
| } |
| |
| mtk_device_wrap_close(fd_target); |
| mtk_device_wrap_close(fd_source); |
| return 0; |
| } |
| |
| int delta_copyto_nand(unsigned int start,int size) |
| { |
| |
| char delta_data[NAND_PAGE_SIZE]; |
| unsigned int ret = 0; |
| int err; |
| |
| |
| if (lseek(fd_delta, start, SEEK_SET) < 0) { |
| LYERRLOG("+[UA]: delta_copyto_nand seek err\n"); |
| return -1; |
| } |
| |
| if (mtk_device_wrap_seek(fd_curr, 0, SEEK_SET) < 0) { |
| LYERRLOG("+[UA]: delta_copyto_nand seek err\n"); |
| return -1; |
| } |
| |
| |
| do { |
| memset(delta_data,0,NAND_PAGE_SIZE); |
| ret = read(fd_delta, delta_data, NAND_PAGE_SIZE); |
| |
| if (ret == 0) { |
| break; |
| } else if (ret < 0) { |
| if (errno == EINTR) { |
| continue; |
| } |
| err = -errno; |
| |
| return err; |
| } |
| |
| size -= NAND_PAGE_SIZE; |
| mtk_device_wrap_write(fd_curr,delta_data,NAND_PAGE_SIZE); |
| //mtk_device_wrap_write(fd_curr,delta_data,ret); |
| |
| } while(size > 0); |
| |
| |
| return 0; |
| |
| } |
| |
| |
| unsigned char ram_buffer[ROCK_RAM_LEN]; |
| |
| int check(int sys_size) |
| { |
| int fd; |
| int i=0; |
| int j=0; |
| int num=i; |
| int n = 0; |
| const uint8_t data[] = { 0x74, 0x77, 0x6f, 0x63, 0x6f, 0x72, 0x65}; |
| const char * core_flag="twocore\n"; |
| |
| uint8_t buffer[16]; |
| |
| if(sys_size == 0)//for only upgrade oemapp and oemapp2 |
| { |
| return 0; |
| } |
| n = strlen(core_flag); |
| lseek(fd_delta,520,SEEK_SET); |
| lseek(fd_delta,sys_size,SEEK_CUR); |
| lseek(fd_delta, -1*n, SEEK_CUR); |
| read(fd_delta, buffer, n); |
| lseek(fd_delta,0,SEEK_SET);//file reset |
| if (memcmp(buffer, core_flag, n) == 0) |
| { |
| return 0; |
| } |
| return -1; |
| |
| } |
| |
| int check_cpu(void) |
| { |
| int i=0; |
| int ret; |
| char buffer[3][64]; |
| FILE *fp; |
| char num; |
| fp = popen("od -x /proc/device-tree/chosen/atag,devinfo","r"); |
| |
| for(i=0;i<3;i++) |
| { |
| fgets(buffer[i], 64, fp); |
| } |
| |
| for(i=0;i<3;i++) |
| { |
| RLOGD("buffer[i] = %s\n",buffer[i]); |
| } |
| RLOGD("%c\n", buffer[2][14]); |
| |
| num = buffer[2][14]; |
| |
| |
| RLOGD("num=%c\n", num); |
| if(num == '0' || num == '1') |
| { |
| printf("this is four core\n"); |
| return 4; |
| } |
| else if(num == '2' || num == '3') |
| { |
| printf("this is two core\n"); |
| return 2; |
| } |
| else |
| { |
| RLOGD("this char is error\n"); |
| return -1; |
| } |
| pclose(fp); |
| |
| return -1; |
| } |
| |
| |
| |
| static int rock_update_main(unsigned int rom_base, unsigned int backup_base, unsigned int backup_len, int read_rom_directly, int first_run, int switch_slot_flag, int |
| reboot_flag, int backup_mode) { |
| int status,err,start,fd; |
| int ret = 0; |
| int i = 0; |
| int retry_cnt = 0; |
| int cpu_flag; |
| IOT_UPDATA_CONTEXT ctx; |
| |
| //OTA_STATUS fota_status; |
| |
| |
| const hw_module_t* hw_module; |
| unsigned int slot; |
| |
| unsigned int update_mode = MODE_NORMAL; |
| unsigned int delta_size; |
| unsigned char full_header[9]; |
| |
| char digest_s[SHA_DIGEST_SIZE]; |
| char digest_t[SHA_DIGEST_SIZE]; |
| char str_sha[40]; |
| char cmd_sys[100]; |
| int core_num; |
| int sha_size = 0; |
| int is_need_fullupdate = 0; |
| int fd_partition_a,fd_partition_b; |
| //xf.li@20230830 add for ab_recover start |
| fd = open(FILE_UPDATE_FLAG,O_RDWR | O_CREAT,0777); |
| if (fd < 0) |
| { |
| RLOGD("+[UA]: can't open file /tmp/update_flag.\n"); |
| return -1; |
| } |
| close(fd); |
| //xf.li@20230830 add for ab_recover end |
| hw_module = &HAL_MODULE_INFO_SYM; |
| |
| if (!hw_module || |
| strcmp(BOOT_CONTROL_HARDWARE_MODULE_ID, hw_module->id) != 0) { |
| ret = -EINVAL; |
| } |
| if (ret != 0) { |
| RLOGD("+[UA]: Error loading boot_control HAL implementation.\n"); |
| return -1; |
| } |
| |
| module = (boot_control_module_t*)hw_module; |
| module->init(module); |
| |
| |
| if (module == NULL) { |
| RLOGD("+[UA]: Error getting bootctrl module.\n"); |
| return -1; |
| } |
| |
| lynq_init_wake_lock_func(); |
| lynq_fota_grab_artial_wake_lock(); |
| /************* Bootctrl Init End *************/ |
| |
| current_slot = module->getCurrentSlot(module); |
| |
| int is_successful = module->isSlotMarkedSuccessful(module, current_slot); |
| |
| RLOGD("Booting slot = %d, : isSlotMarkedSuccessful= %d\n",current_slot,is_successful); |
| |
| |
| |
| memset(&ctx, 0, sizeof(ctx)); |
| ctx.rom_base = 0; |
| ctx.ram_base =(unsigned char *)&ram_buffer[0]; |
| ctx.ram_len = ROCK_RAM_LEN; |
| ctx.backup_base = BACKUP_ADDR_FLAG; |
| //ctx.backup_len = ROCK_DEFAULT_BLOCK_SIZE; |
| ctx.backup_len = 0; |
| ctx.update_nvram = 0; |
| ctx.read_rom_directly = read_rom_directly; |
| //ctx.first_run = first_run; |
| ctx.first_run = 1; |
| |
| if(0 != init_dev_fd()) |
| { |
| RLOGD("+[UA]: get fota addr error\n"); |
| system("echo fota-interface >/sys/power/wake_unlock"); |
| return E_ROCK_FOTA_ADDR; |
| } |
| |
| |
| memset(&fota_status,0,sizeof(fota_status)); |
| RLOGD("+[UA]: up_info.ota_run = %d\n",up_info.ota_run); |
| |
| #if 0 |
| if ((up_info.ota_run>PATCH_BL33)||(up_info.ota_run<PATCH_SYSTEM)) |
| { |
| up_info.ota_run = 0; |
| } |
| #endif |
| |
| up_info.ota_run = 0; |
| if(backup_mode == 1) |
| { |
| if(current_slot == 0) |
| { |
| update_mode = MODE_A2B; |
| }else |
| { |
| update_mode = MODE_B2A; |
| } |
| } |
| else |
| { |
| update_mode = MODE_NORMAL; |
| } |
| |
| RLOGD("+[UA]: up_info.fota_flag = %s\n",up_info.fota_flag); |
| RLOGD("+[UA]: update_mode = %d\n",update_mode); |
| |
| //memset(&da_head, 0, sizeof(da_head)); |
| |
| //read(fd_delta, (unsigned char*)&da_head, sizeof(da_head)); |
| |
| memset(&delta_head, 0, sizeof(delta_head)); |
| read(fd_delta, (char *)&delta_head[0], sizeof(delta_head)); |
| |
| |
| delta_size = 0; |
| sha_size = 0; |
| for (i = 0;i<REAL_OTA_ROLE; i++) { |
| if (delta_head[i] > 0) { |
| fota_status.update_status[i].need_update = 1; |
| delta_size+=delta_head[i]; |
| |
| } |
| RLOGD("+[UA]: %s,delta size = %d\n",partition_filename[i],delta_head[i]); |
| } |
| |
| |
| for(i = MAX_OTA_ROLE/2;i<(MAX_OTA_ROLE/2+REAL_OTA_ROLE); i++) { |
| if (delta_head[i] > 0) { |
| fota_status.update_status[i].need_update = 1; |
| sha_size+=delta_head[i]; |
| } |
| RLOGD("+[UA]: %s,full size = %d, i=%d\n",partition_filename[i-MAX_OTA_ROLE/2],delta_head[i], i); |
| } |
| |
| core_num= check_cpu(); |
| if(core_num == 2) |
| { |
| cpu_flag = check(delta_head[64]); |
| if(cpu_flag < 0) |
| { |
| RLOGD("cpu core is error\n"); |
| system("echo fota-interface >/sys/power/wake_unlock"); |
| return -1; |
| } |
| else |
| { |
| RLOGD("cpu core match\n"); |
| } |
| } |
| else if(core_num == 4) |
| { |
| RLOGD("the cpu core is four!!!\n"); |
| } |
| else |
| { |
| RLOGD("read the cpu core fail"); |
| system("echo fota-interface >/sys/power/wake_unlock"); |
| return -1; |
| } |
| |
| fota_status.switch_slot = WAIT; |
| save_fota_status(); |
| |
| //delta_size = da_head.sys + da_head.boot + da_head.tee + da_head.md1img + da_head.md1dsp + da_head.vbmeta + da_head.oemapp + da_head.oemapp2 + da_head.medmcu+da_head.bl33; |
| |
| //sha_size = da_head.full_sys + da_head.full_boot + da_head.full_tee + da_head.full_md1img + da_head.full_md1dsp + da_head.full_vbmeta + da_head.full_oemapp + da_head.full_oemapp2 + da_head.full_medmcu+da_head.full_bl33 |
| |
| |
| |
| |
| is_need_fullupdate = 0; |
| if(sha_size>0) { |
| is_need_fullupdate = 1; |
| sha_size+=8; |
| } |
| |
| sha_size+=delta_size; |
| |
| memset(digest_s,0,SHA_DIGEST_SIZE); |
| memset(digest_t,0,SHA_DIGEST_SIZE); |
| memset(str_sha,0,40); |
| |
| lseek(fd_delta, sha_size + sizeof(delta_head), SEEK_SET); |
| read(fd_delta, digest_s, SHA_DIGEST_SIZE); |
| convert_hex(digest_s,str_sha); |
| RLOGD("+[UA]: delta save sha = %s\n",str_sha); |
| |
| ROCK_SHA_FILE_COMMON(fd_delta,sizeof(delta_head),sha_size,digest_t); |
| memset(str_sha,0,40); |
| convert_hex(digest_t,str_sha); |
| RLOGD("+[UA]: delta calc sha = %s\n",str_sha); |
| |
| if(memcmp(digest_s,digest_t,SHA_DIGEST_SIZE)==0) { |
| |
| RLOGD("sha verify pass\n"); |
| |
| }else{ |
| RLOGD("delta sha verify fial!\n"); |
| |
| system("echo fota-interface >/sys/power/wake_unlock"); |
| return -1; |
| |
| } |
| |
| memset(digest_s,0,SHA_DIGEST_SIZE); |
| memset(digest_t,0,SHA_DIGEST_SIZE); |
| |
| |
| //delta_offset = DELTA_HEARD_SIZE; |
| delta_offset = sizeof(delta_head); |
| |
| for(i = 0;i<REAL_OTA_ROLE; i++){ //diff |
| //now_patch = i+1; |
| if (i>0) { |
| delta_offset+=delta_head[i-1]; |
| } |
| if((delta_head[i]>0) && (up_info.ota_run<=(i+1))){ |
| now_patch = i + 1; |
| #if 0 |
| if (up_info.ota_run == now_patch) //升级ps断电? |
| { |
| ctx.first_run = 0; |
| |
| }else{ |
| ctx.first_run = 1; |
| } |
| #endif |
| ctx.first_run = 1; //always |
| RLOGD("+[UA]: PATCH %s,ctx.first_run = %d\n", partition_filename[i] ,ctx.first_run); |
| up_info.ota_run = now_patch; |
| |
| if(current_slot==SLOT_B) { |
| sprintf(cmd_sys,"flash_eraseall %s",partition_filename_a[i]); |
| }else{ |
| sprintf(cmd_sys,"flash_eraseall %s",partition_filename_b[i]); |
| } |
| system(cmd_sys); |
| |
| |
| fd_partition_a = mtk_device_wrap_open(partition_filename_a[i],O_RDWR); |
| if (fd_partition_a < 0) { |
| err = errno; |
| RLOGD("+[UA]: Error opening id_a[%d] file: %s\n",i,strerror(errno)); |
| system("echo fota-interface >/sys/power/wake_unlock"); |
| return -err; |
| } |
| |
| fd_partition_b = mtk_device_wrap_open(partition_filename_b[i],O_RDWR); |
| if (fd_partition_b < 0) { |
| err = errno; |
| RLOGD("+[UA]: Error opening id_b[%d] file: %s\n",i,strerror(errno)); |
| system("echo fota-interface >/sys/power/wake_unlock"); |
| return -err; |
| } |
| if(current_slot==SLOT_B){ |
| fd_read = fd_partition_b; |
| fd_write = fd_partition_a; |
| } else { |
| fd_read = fd_partition_a; |
| fd_write = fd_partition_b; |
| } |
| |
| fota_status.ota_run = i; |
| fota_status.update_status[i].check_delta = WAIT; |
| fota_status.update_status[i].check_rom = WAIT; |
| fota_status.update_status[i].update_result= WAIT; |
| |
| save_fota_status(); |
| |
| |
| up_info.ota_run = i+1; |
| save_fota_info(); |
| |
| RLOGD("+[UA]: Start upgrading %s.\n",partition_filename[i]); |
| status = iot_patch(&ctx); |
| RLOGD("+[UA]: %s upgrade result:%d\n",partition_filename[i],status); |
| |
| //up_info.ota_run = 0; |
| |
| //fota_status.ota_run = 0; |
| fota_status.update_status[i].update_result= status; |
| fota_status.update_result= status; |
| |
| if((status == 0)||(status ==1)) |
| { |
| |
| fota_status.update_status[i].check_delta = PASS; |
| fota_status.update_status[i].check_rom = PASS; |
| RLOGD("+[UA]: %s upgrade success!!!\n",partition_filename[i]); |
| |
| }else if(status == E_ROCK_INVALID_DELTA) { |
| fota_status.update_status[i].check_delta = ERROR; |
| fota_status.update_status[i].check_rom = WAIT; |
| }else if((status == E_ROCK_DELTA_MISMATCH)||(status == E_ROCK_DELTA_CHUNK_MISMATCH)) { |
| fota_status.update_status[i].check_delta = PASS; |
| fota_status.update_status[i].check_rom = ERROR; |
| |
| }else{ |
| |
| //fota_status.update_status[PATCH_SYSTEM -1].check_delta = PASS; |
| //fota_status.update_status[PATCH_SYSTEM -1].check_rom = WAIT; |
| } |
| |
| save_fota_status(); |
| |
| |
| if ((status != 0) &&(status != 1)) |
| { |
| |
| up_info.fota_flag[0] = 'e'; |
| up_info.fota_flag[1] = 'n'; |
| up_info.fota_flag[2] = 'd'; |
| up_info.update_result = status; |
| up_info.ota_run = 0; |
| save_fota_info(); |
| |
| mtk_device_wrap_close(fd_read); |
| mtk_device_wrap_close(fd_write); |
| |
| system("echo fota-interface >/sys/power/wake_unlock"); |
| return status; |
| } |
| mtk_device_wrap_close(fd_read); |
| mtk_device_wrap_close(fd_write); |
| |
| } |
| |
| } |
| |
| |
| |
| if (is_need_fullupdate == 1) |
| { |
| |
| now_patch = 0; |
| up_info.ota_run = 0; |
| |
| memset(&fota_status,0,sizeof(fota_status)); |
| fota_status.switch_slot = WAIT; |
| save_fota_status(); |
| |
| if (lseek(fd_delta, DELTA_HEARD_SIZE + delta_size, SEEK_SET) < 0) { |
| err = errno; |
| RLOGD("+[UA]: mtk_device_wrap_seek df_delta err\n"); |
| system("echo fota-interface >/sys/power/wake_unlock"); |
| return -1; |
| } |
| |
| read(fd_delta, full_header, DELTA_FULL_HEARD_SIZE); |
| |
| |
| if (memcmp(full_header, "full-ota", DELTA_FULL_HEARD_SIZE) != 0) { |
| RLOGD("+[UA]: invalid full delta header\r\n"); |
| up_info.fota_flag[0] = 'e'; |
| up_info.fota_flag[1] = 'n'; |
| up_info.fota_flag[2] = 'd'; |
| up_info.update_result = -1; |
| up_info.ota_run = 0; |
| save_fota_info(); |
| |
| //for (i = FULL_SYSTEM;i<=FULL_BL33;i++){ |
| |
| for (i = MAX_OTA_ROLE/2;i<(MAX_OTA_ROLE/2+REAL_OTA_ROLE);i++){ |
| if (fota_status.update_status[i].need_update ==1) { |
| fota_status.ota_run = i; |
| fota_status.update_status[i].check_delta = ERROR; |
| fota_status.update_status[i].check_rom= WAIT; |
| fota_status.update_status[i].update_result= ERROR; |
| } |
| } |
| fota_status.update_result = ERROR; |
| save_fota_status(); |
| system("echo fota-interface >/sys/power/wake_unlock"); |
| return -1; |
| } |
| } |
| |
| |
| |
| delta_offset = DELTA_HEARD_SIZE + delta_size + DELTA_FULL_HEARD_SIZE; |
| |
| for(i = MAX_OTA_ROLE/2;i<(MAX_OTA_ROLE/2+REAL_OTA_ROLE);i++) { |
| |
| if (i>MAX_OTA_ROLE/2) { |
| delta_offset+=delta_head[i-1]; |
| } |
| if(delta_head[i]>0) { |
| |
| if(current_slot==SLOT_B) { |
| sprintf(cmd_sys,"flash_eraseall %s",partition_filename_a[i-MAX_OTA_ROLE/2]); |
| } else { |
| sprintf(cmd_sys,"flash_eraseall %s",partition_filename_b[i-MAX_OTA_ROLE/2]); |
| } |
| system(cmd_sys); |
| |
| if(current_slot==SLOT_B) { |
| fd_partition_a = mtk_device_wrap_open(partition_filename_a[i-MAX_OTA_ROLE/2],O_RDWR); |
| if (fd_partition_a < 0) { |
| err = errno; |
| RLOGD("+[UA]: Error opening full id_a[%d] file: %s\n",i,strerror(errno)); |
| system("echo fota-interface >/sys/power/wake_unlock"); |
| return -err; |
| } |
| fd_curr = fd_partition_a; |
| }else{ |
| fd_partition_b = mtk_device_wrap_open(partition_filename_b[i-MAX_OTA_ROLE/2],O_RDWR); |
| if (fd_partition_b < 0) { |
| err = errno; |
| RLOGD("+[UA]: Error opening full_id_b[%d] file: %s\n",i,strerror(errno)); |
| system("echo fota-interface >/sys/power/wake_unlock"); |
| return -err; |
| } |
| fd_curr = fd_partition_b; |
| } |
| fota_status.ota_run = i+1; |
| save_fota_status(); |
| up_info.ota_run = i+1; |
| save_fota_info(); |
| retry_cnt = 0; |
| RLOGD("+[UA]: Start upgrading %s full.\n",partition_filename[i-MAX_OTA_ROLE/2]); |
| do{ |
| status = delta_copyto_nand(delta_offset,delta_head[i]); |
| |
| ROCK_SHA_FILE_COMMON(fd_delta,delta_offset,delta_head[i],digest_s); |
| ROCK_SHA_FILE(fd_curr,0,delta_head[i],digest_t); |
| retry_cnt++; |
| }while((strncmp(digest_s,digest_t,SHA_DIGEST_SIZE)!=0)&&(retry_cnt <= 3)); |
| |
| mtk_device_wrap_close(fd_curr); |
| |
| RLOGD("+[UA]: %s full retry_cnt = %d\n",partition_filename[i-MAX_OTA_ROLE/2],retry_cnt); |
| |
| if (retry_cnt>3) { |
| if (status == 0) { |
| status = retry_cnt; |
| } |
| if(current_slot==SLOT_B) { |
| nand_copyto_nand(partition_filename_b[i-MAX_OTA_ROLE/2],partition_filename_a[i-MAX_OTA_ROLE/2]); |
| } |
| else{ |
| nand_copyto_nand(partition_filename_a[i-MAX_OTA_ROLE/2],partition_filename_b[i-MAX_OTA_ROLE/2]); |
| } |
| } |
| |
| RLOGD("+[UA]: %s full upgrade result:%d\n",partition_filename[i-MAX_OTA_ROLE/2],status); |
| |
| fota_status.update_result = status; |
| fota_status.update_status[i].update_result = status; |
| save_fota_status(); |
| |
| if (status != 0) |
| { |
| |
| up_info.fota_flag[0] = 'e'; |
| up_info.fota_flag[1] = 'n'; |
| up_info.fota_flag[2] = 'd'; |
| up_info.update_result = status; |
| up_info.ota_run = 0; |
| save_fota_info(); |
| system("echo fota-interface >/sys/power/wake_unlock"); |
| return status; |
| } |
| |
| } |
| |
| } |
| |
| |
| |
| |
| if(update_mode != MODE_NORMAL){ //need backup |
| if(current_slot == SLOT_A) { |
| up_info.fota_flag[0] = 'B'; |
| up_info.fota_flag[1] = '-'; |
| up_info.fota_flag[2] = 'A'; |
| |
| }else{ |
| up_info.fota_flag[0] = 'A'; |
| up_info.fota_flag[1] = '-'; |
| up_info.fota_flag[2] = 'B'; |
| |
| } |
| |
| }else{ |
| up_info.fota_flag[0] = 'e'; |
| up_info.fota_flag[1] = 'n'; |
| up_info.fota_flag[2] = 'd'; |
| |
| } |
| |
| |
| up_info.update_result = status; |
| up_info.ota_run = 0; |
| save_fota_info(); |
| |
| //close_dev_fd(fd_curr); |
| |
| |
| |
| close(fd_update_status); |
| sync(); |
| |
| |
| slot = (current_slot == 0) ? 1 : 0; |
| |
| RLOGD("+[UA]: slot SLOT = %d\n",slot); |
| |
| if(switch_slot_flag==1) |
| { |
| module->setActiveBootSlot(module,slot); |
| RLOGD("+[UA]: upgrade is success!!!!\n"); |
| } |
| |
| fota_status.ota_run = 0; |
| fota_status.switch_slot = PASS; |
| fota_status.update_result = status; |
| save_fota_status(); |
| |
| sleep(5); |
| sync(); |
| sleep(5); |
| |
| system("echo fota-interface >/sys/power/wake_unlock"); |
| |
| if(reboot_flag==1){ |
| reboot_device(); |
| } |
| |
| return status; |
| } |
| |
| |
| |
| static void rock_fail_handler() |
| { |
| int ret = 0; |
| RLOGD("rock_fail_handler start\n"); |
| //ret = rock_update_main(0, 0, 0, 0, 1, 1); |
| if(ret) |
| { |
| RLOGD("fota update fail again!\n"); |
| } |
| } |
| |
| /* main entrpoint */ |
| int lynq_rock_main(int first_run) |
| { |
| |
| int ret = 0; |
| |
| #if 0 |
| |
| printf("-********copy delta ***-\n"); |
| test_write_delta("/data/delta",DEV_DELTA); |
| |
| #endif |
| |
| ret = rock_update_main(0, 0, 0, 0, first_run, 1, 1, 1); |
| RLOGD("rock_update_main ret = %d\n", ret); |
| if(ret) |
| { |
| RLOGD("fota update fail!\n"); |
| } |
| return ret; |
| } |
| |
| #endif |
| |
| //xf.li@20230403 add for verfy start |
| int lynq_file_md5_verfy(char *source, unsigned char *source_md5, char *target) |
| { |
| int fd, size, ret, is_system = 0; |
| int need_copy = 1; |
| int system_mtd_num = 0; |
| int system_ubi_num = BACKUP_UBI_NUM;//max ubi number |
| char cmd_ubi_attach[128] = {0}; |
| char cmd_ubi_detach[128] = {0}; |
| char md5_target_file_patch[128] = {0}; |
| |
| RLOGD("in lynq_file_md5_verfy, source:%s, target:%s\n", source, target); |
| if(strcmp(source, DEV_SYSTEM_A) == 0 || strcmp(source, DEV_SYSTEM_B) == 0) |
| { |
| RLOGD("verfy system.img\n"); |
| is_system = 1; |
| if(strcmp(source, DEV_SYSTEM_A) == 0) |
| { |
| system_mtd_num = MTD_SYSTEM_B; |
| } |
| else if(strcmp(source, DEV_SYSTEM_B) == 0) |
| { |
| system_mtd_num = MTD_SYSTEM_A; |
| } |
| else |
| { |
| RLOGD("source:%s, target:%s\n", source, target); |
| } |
| for( ; system_ubi_num >= 10; system_ubi_num--)//try from ubi31 to ubi10 |
| { |
| sprintf(md5_target_file_patch, "/dev/ubi%d", system_ubi_num); |
| RLOGD("ubi_num = %d\n", system_ubi_num); |
| if((access(md5_target_file_patch, F_OK)) == -1) |
| { |
| RLOGD("no the ubi file, can use this ubi.\n"); |
| break; |
| } |
| } |
| if(system_ubi_num < 10) |
| { |
| RLOGE("no the ubi file, can use this ubi.\n"); |
| return -1; |
| } |
| } |
| //=========================caculate md5sum start===================== |
| if(is_system == 1) |
| { |
| RLOGD("in system caculate\n"); |
| RLOGD("system_mtd_num = %d, ubi_num = %d\n", system_mtd_num, system_ubi_num); |
| sprintf(cmd_ubi_attach, "ubiattach /dev/ubi_ctrl -m %d -d %d", system_mtd_num, system_ubi_num); |
| RLOGD("cmd_ubi_attach:%s", cmd_ubi_attach); |
| ret = system(cmd_ubi_attach); |
| if(ret != 0) |
| { |
| RLOGE("ubi attach error!!!\n"); |
| return need_copy; |
| } |
| RLOGD("attach over\n"); |
| //attach success |
| sprintf(md5_target_file_patch, "/dev/ubi%d_0", system_ubi_num); |
| RLOGD("md5_target_file_patch:%s", md5_target_file_patch); |
| //make sure the ubi volume is exist |
| if((access(md5_target_file_patch, F_OK)) == -1) |
| { |
| RLOGD("no the ubi file.\n"); |
| sprintf(cmd_ubi_detach, "ubidetach -m %d", system_mtd_num); |
| ret = system(cmd_ubi_detach); |
| if(ret != 0) |
| { |
| RLOGD("ubi dettach error!!!\n"); |
| } |
| |
| return need_copy; |
| } |
| //calculate md5sum |
| //ret = lynq_md5_two_file_verfy("/dev/ubi0_0", md5_target_file_patch); |
| ret = lynq_md5_file_verfy_ab(md5_target_file_patch, source_md5); |
| if(ret == MD5_VERFY_ERROR) |
| { |
| //ubidetach |
| sprintf(cmd_ubi_detach, "ubidetach -m %d", system_mtd_num); |
| ret = system(cmd_ubi_detach); |
| if(ret != 0) |
| { |
| RLOGD("ubi dettach error!!!\n"); |
| } |
| return need_copy; |
| } |
| if(ret != 0) |
| { |
| //ubidetach |
| sprintf(cmd_ubi_detach, "ubidetach -m %d", system_mtd_num); |
| ret = system(cmd_ubi_detach); |
| if(ret != 0) |
| { |
| RLOGD("ubi dettach error!!!\n"); |
| } |
| RLOGD("calculate system error!!!\n"); |
| return -1; |
| } |
| |
| RLOGD("verfy system.img over\n"); |
| } |
| else |
| { |
| RLOGD("verfy else img\n"); |
| //calculate md5sum |
| //ret = lynq_md5_two_file_verfy(source, target); |
| ret = lynq_md5_file_verfy_ab(target, source_md5); |
| if(ret == MD5_VERFY_ERROR) |
| { |
| return need_copy; |
| } |
| if(ret != 0) |
| { |
| RLOGD("calculate %s and %s error!!!\n", source, target); |
| return -1; |
| } |
| } |
| //====================caculate md5sum end====================== |
| return 0; |
| } |
| //xf.li@20230403 add for verfy end |
| |
| |
| //xf.li@20230401 add for ab rollback start |
| |
| int backup_nand_copyto_nand(char *source, char *target) |
| { |
| int fd_source, fd_target, size; |
| int ret = -1; |
| int sleep_count = 0; |
| char cmd_erase_target[128] = {0}; |
| int retry = MD5_RETRY_TIME; |
| unsigned char source_md5[MD5_READ_BUFFER_LEN] = {0}; |
| char delta_data[ROCK_DEFAULT_BLOCK_SIZE]; |
| //caclculate source md5 start |
| if(strcmp(source, DEV_SYSTEM_A) == 0 || strcmp(source, DEV_SYSTEM_B) == 0) |
| { |
| RLOGD("backup_nand_copyto_nand: verfy system.img\n"); |
| |
| ret = calculate_file_md5_value("/dev/ubi0_0", source_md5); |
| if(ret < 0) |
| { |
| RLOGD("[+MD5]:calculate source md5 value ERROE!!!\n"); |
| return ret; |
| } |
| RLOGD("source_md5 is %s\n", source_md5); |
| } |
| else |
| { |
| ret = calculate_file_md5_value(source, source_md5); |
| if(ret < 0) |
| { |
| RLOGD("[+MD5]:calculate source md5 value ERROE!!!\n"); |
| return ret; |
| } |
| RLOGD("source_md5 is %s\n", source_md5); |
| } |
| //caclculate source md5 end |
| //ret = lynq_file_md5_verfy(source, target);//verfy md5 value |
| ret = lynq_file_md5_verfy(source, source_md5, target);//verfy md5 value |
| RLOGD("+[UA]: md5_file_verfy :ret=%d\n", ret); |
| if(ret == 0) |
| { |
| RLOGD("+[UA]: nand_copyto_nand don't neet copy\n"); |
| } |
| for(; ret > 0 && retry > 0; retry--) |
| { |
| //erase nand-target start |
| if(fota_interrupt == FOTA_FIRST && (access(FILE_UPDATE_FLAG, F_OK)) == 0) |
| { |
| RLOGD("+[UA]: fota runing\n"); |
| return -1; |
| } |
| acquire_wake_lock(PARTIAL_WAKE_LOCK, "ab_recover");//lock |
| RLOGD("+[UA]: ready to flash_erase\n"); |
| sprintf(cmd_erase_target, "flash_erase %s 0 0", target); |
| ret = system(cmd_erase_target); |
| release_wake_lock("ab_recover");//unlock |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: erase %s fail\n", target); |
| return -1; |
| } |
| sleep(1);//sleep 1s |
| |
| //erase nand-target end |
| RLOGD("+[UA]: ready to copy\n"); |
| fd_source = mtk_device_wrap_open(source, O_RDONLY); |
| if (fd_source < 0) { |
| RLOGD("+[UA]: open source error\n"); |
| return -1; |
| } |
| |
| fd_target = mtk_device_wrap_open(target, O_RDWR); |
| if (fd_target < 0) { |
| RLOGD("+[UA]: open target error\n"); |
| return -1; |
| } |
| ret = 0;//init ret |
| acquire_wake_lock(PARTIAL_WAKE_LOCK, "ab_recover");//lock |
| while(( size = mtk_device_wrap_read(fd_source,delta_data,ROCK_DEFAULT_BLOCK_SIZE))>0) |
| { |
| if(fota_interrupt == FOTA_FIRST && (access(FILE_UPDATE_FLAG, F_OK)) == 0) |
| { |
| RLOGD("+[UA]: fota runing\n"); |
| ret = -1; |
| break; |
| } |
| usleep(40000);//sleep 40ms |
| mtk_device_wrap_write(fd_target,delta_data,ROCK_DEFAULT_BLOCK_SIZE); |
| usleep(60000);//sleep 60ms |
| sleep_count++; |
| if(sleep_count >= 20) |
| { |
| //unlock |
| release_wake_lock("ab_recover"); |
| sleep(1);//sleep 1s |
| //lock |
| acquire_wake_lock(PARTIAL_WAKE_LOCK, "ab_recover"); |
| sleep_count = 0; |
| RLOGD("+[UA]: try sleep one time"); |
| } |
| } |
| release_wake_lock("ab_recover");//unlock |
| RLOGD("+[UA]: copy end\n"); |
| mtk_device_wrap_close(fd_target); |
| mtk_device_wrap_close(fd_source); |
| if(ret < 0) |
| { |
| RLOGD("+[UA]: ret < 0\n"); |
| return -1; |
| } |
| RLOGD("+[UA]: ready to md5_verfy\n"); |
| //ret = lynq_file_md5_verfy(source, target);//verfy md5 value |
| ret = lynq_file_md5_verfy(source, source_md5, target);//verfy md5 value |
| RLOGD("+[UA]: md5_file_verfy :ret=%d\n", ret); |
| if(ret == 0) |
| { |
| RLOGD("+[UA]: nand_copyto_nand copy success\n"); |
| break; |
| } |
| } |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: md5_file_verfy FAIL!!!\n"); |
| } |
| return ret; |
| } |
| //xf.li@20230401 add for ab rollback end |
| |
| //xf.li@20230822 add for ab rollback start |
| |
| int lynq_backup_main() |
| { |
| const hw_module_t* hw_module; |
| hw_module = &HAL_MODULE_INFO_SYM; |
| int is_successful; |
| int ret = 0; |
| if (!hw_module || strcmp(BOOT_CONTROL_HARDWARE_MODULE_ID, hw_module->id) != 0) |
| { |
| ret = -1; |
| } |
| RLOGD("ret = %d\n", ret); |
| if (ret != 0) |
| { |
| RLOGD("+[UA]: Error loading boot_control HAL implementation.\n"); |
| return -1; |
| } |
| module = (boot_control_module_t*)hw_module; |
| module->init(module); |
| if (module == NULL) |
| { |
| RLOGD("+[UA]: Error getting bootctrl module.\n"); |
| return -1; |
| } |
| lynq_init_wake_lock_func(); |
| current_slot = module->getCurrentSlot(module); |
| is_successful = module->isSlotMarkedSuccessful(module, current_slot); |
| RLOGD("+[UA]: Booting slot = %d, : isSlotMarkedSuccessful= %d\n",current_slot,is_successful); |
| fota_interrupt = RECOVER_FIRST; |
| if(current_slot==SLOT_B) |
| { |
| ret = backup_nand_copyto_nand(DEV_SPM_B,DEV_SPM_A); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup spm_a fail\n"); |
| return 1; |
| } |
| fota_interrupt = FOTA_FIRST; |
| ret = backup_nand_copyto_nand(DEV_SYSTEM_B,DEV_SYSTEM_A); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup system_a fail\n"); |
| return 1; |
| } |
| ret = backup_nand_copyto_nand(DEV_BOOT_B,DEV_BOOT_A); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup boot_a fail\n"); |
| return 1; |
| } |
| ret = backup_nand_copyto_nand(DEV_TEE_B,DEV_TEE_A); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup tee_a fail\n"); |
| return 1; |
| } |
| ret = backup_nand_copyto_nand(DEV_MD1IMG_B,DEV_MD1IMG_A); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup md1img_a fail\n"); |
| return 1; |
| } |
| ret = backup_nand_copyto_nand(DEV_VBMETA_B,DEV_VBMETA_A); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup vbmeta_a fail\n"); |
| return 1; |
| } |
| ret = backup_nand_copyto_nand(DEV_MEDMCU_B,DEV_MEDMCU_A); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup medmcu_a fail\n"); |
| return 1; |
| } |
| ret = backup_nand_copyto_nand(DEV_BL2_B,DEV_BL2_A); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup bl2_a fail\n"); |
| return 1; |
| } |
| ret = backup_nand_copyto_nand(DEV_BL33_B,DEV_BL33_A); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup bl33_a fail\n"); |
| return 1; |
| } |
| ret = backup_nand_copyto_nand(DEV_OEMAPP_B,DEV_OEMAPP_A); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup oemapp_a fail\n"); |
| return 1; |
| } |
| ret = backup_nand_copyto_nand(DEV_OEMAPP2_B,DEV_OEMAPP2_A); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup oemapp2_a fail\n"); |
| return 1; |
| } |
| } |
| else |
| { |
| ret = backup_nand_copyto_nand(DEV_SPM_A,DEV_SPM_B); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup spm_a fail\n"); |
| return 1; |
| } |
| fota_interrupt = FOTA_FIRST; |
| ret = backup_nand_copyto_nand(DEV_SYSTEM_A,DEV_SYSTEM_B); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup system_b fail\n"); |
| return 1; |
| } |
| ret = backup_nand_copyto_nand(DEV_BOOT_A,DEV_BOOT_B); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup boot_b fail\n"); |
| return 1; |
| } |
| |
| ret = backup_nand_copyto_nand(DEV_TEE_A,DEV_TEE_B); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup tee_b fail\n"); |
| return 1; |
| } |
| ret = backup_nand_copyto_nand(DEV_MD1IMG_A,DEV_MD1IMG_B); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup md1img_b fail\n"); |
| return 1; |
| } |
| ret = backup_nand_copyto_nand(DEV_VBMETA_A,DEV_VBMETA_B); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup vbmeta_b fail\n"); |
| return 1; |
| } |
| ret = backup_nand_copyto_nand(DEV_MEDMCU_A,DEV_MEDMCU_B); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup medmcu_b fail\n"); |
| return 1; |
| } |
| ret = backup_nand_copyto_nand(DEV_BL2_A,DEV_BL2_B); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup bl2_a fail\n"); |
| return 1; |
| } |
| ret = backup_nand_copyto_nand(DEV_BL33_A,DEV_BL33_B); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup bl33_a fail\n"); |
| return 1; |
| } |
| ret = backup_nand_copyto_nand(DEV_OEMAPP_A,DEV_OEMAPP_B); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup oemapp_b fail\n"); |
| return 1; |
| } |
| ret = backup_nand_copyto_nand(DEV_OEMAPP2_A,DEV_OEMAPP2_B); |
| if(ret != 0) |
| { |
| RLOGD("+[UA]: backup oemapp2_b fail\n"); |
| return 1; |
| } |
| } |
| RLOGD("+[UA]: lynq_backup_main success \n"); |
| return 0; |
| } |
| //xf.li@20230822 add for ab rollback end |
| |
| |
| int lynq_check_oemapp(char* name) |
| { |
| FILE *fp; |
| char check_result[64]; |
| if(strcmp(name, "oemapp") == 0) |
| { |
| RLOGD("lynq_check_oemapp oemapp"); |
| if(system("df -lh|grep oemapp |grep -v oemapp2") != 0) |
| { |
| return 0; |
| } |
| else |
| { |
| return 1; |
| } |
| } |
| else if(strcmp(name, "oemapp2") == 0) |
| { |
| RLOGD("lynq_check_oemapp oemapp2"); |
| if(system("df -lh|grep oemapp2") != 0) |
| { |
| return 0; |
| } |
| else |
| { |
| return 1; |
| } |
| } |
| } |
| |
| //lt add @2021.9.23 for deal with power down \ backup or upgrade. |
| int lynq_fota_func(void) |
| { |
| int fd; |
| int first_run = 1; |
| int ret = 0; |
| UPDATE_INFO lynq_up_info; |
| //xf.li@20230822 add for ab backup start |
| unsigned int current_slot, other_slot; |
| int is_other_slot_bootable; |
| const hw_module_t* hw_module; |
| //xf.li@20230822 add for ab backup end |
| RLOGD("[+UP]: ******lynq_fota_func start******\n"); |
| //xf.li@20230822 add for ab backup start |
| //----------get current slot and whether other slot is bootable |
| hw_module = &HAL_MODULE_INFO_SYM; |
| if (!hw_module || |
| strcmp(BOOT_CONTROL_HARDWARE_MODULE_ID, hw_module->id) != 0) { |
| ret = -EINVAL; |
| } |
| if (ret != 0) { |
| RLOGD("+[UA]: Error loading boot_control HAL implementation.\n"); |
| return -1; |
| } |
| module = (boot_control_module_t*)hw_module; |
| module->init(module); |
| if (module == NULL) { |
| RLOGD("+[UA]: Error getting bootctrl module.\n"); |
| return -1; |
| } |
| current_slot = module->getCurrentSlot(module); |
| other_slot = (current_slot == 0) ? 1 : 0; |
| is_other_slot_bootable = module->isSlotBootable(module, other_slot); |
| //-----------end |
| RLOGD("current slot:%u, is_other_slot_bootable : %d\n",current_slot, is_other_slot_bootable); |
| //xf.li@20230822 add for ab backup end |
| |
| memset(&lynq_up_info, 0, sizeof(lynq_up_info)); |
| fd = open(FILE_UPDATE_STATE,O_RDWR | O_CREAT,0777); |
| if (fd < 0) |
| { |
| return -1; |
| } |
| read(fd,(unsigned char *)&lynq_up_info,sizeof(lynq_up_info)); |
| close(fd); |
| |
| RLOGD("[+UP]: lynq_up_info.ota_run=%d\n",lynq_up_info.ota_run); |
| if((lynq_check_oemapp("oemapp") == 0) || (lynq_check_oemapp("oemapp2") == 0)) |
| { |
| RLOGD("ENTER LYNQ_CHECK_OEMAPP\n"); |
| system("echo mode 001 0 > /sys/devices/platform/10005000.pinctrl/mt_gpio"); |
| system("echo dir 001 1 > /sys/devices/platform/10005000.pinctrl/mt_gpio"); |
| system("echo out 001 1 > /sys/devices/platform/10005000.pinctrl/mt_gpio"); |
| RLOGD("need setUnbootable.\n"); |
| module->setSlotAsUnbootable(module,current_slot); |
| RLOGD("+[UA]: setSlotAsUnbootable!!!!\n"); |
| sync(); |
| if(((lynq_up_info.fota_flag[0]=='A')&&(lynq_up_info.fota_flag[1]=='-')&&(lynq_up_info.fota_flag[2]=='B'))|| |
| ((lynq_up_info.fota_flag[0]=='B')&&(lynq_up_info.fota_flag[1]=='-')&&(lynq_up_info.fota_flag[2]=='A'))) |
| { |
| RLOGD("mark oemapp mount fail\n"); |
| lynq_set_value(FOTA_UCI_MODULE,FOTA_UCI_STATE, "1"); |
| } |
| sleep(5); |
| reboot_device(); |
| } |
| |
| |
| if(lynq_up_info.ota_run != 0) |
| { |
| //Power off, call UA |
| RLOGD("[+UP]: ***Power off, call UA***\n"); |
| ret = rock_update_main(0, 0, 0, 0, first_run, 1, 0, 1); |
| RLOGD("rock_update_main ret = %d\n", ret); |
| if(ret) |
| { |
| RLOGD("fota update fail!\n"); |
| } |
| } |
| |
| if(((lynq_up_info.fota_flag[0]=='A')&&(lynq_up_info.fota_flag[1]=='-')&&(lynq_up_info.fota_flag[2]=='B'))|| |
| ((lynq_up_info.fota_flag[0]=='B')&&(lynq_up_info.fota_flag[1]=='-')&&(lynq_up_info.fota_flag[2]=='A'))) |
| { |
| //Upgrade the other side and call UA |
| RLOGD("[+UP]: ***Upgrade the other side and call UA***\n"); |
| ret = rock_update_main(0, 0, 0, 0, first_run, 0, 0, 0); |
| RLOGD("rock_update_main ret = %d\n", ret); |
| if(ret) |
| { |
| RLOGD("fota update fail!\n"); |
| } |
| } |
| //xf.li@20230822 add for ab backup start |
| else if(is_other_slot_bootable == 0) |
| { |
| RLOGD("need backup\n"); |
| ret = lynq_backup_main(); |
| if(ret != 0) |
| { |
| RLOGD("ERROE: backup fail!!!\n"); |
| } |
| else |
| { |
| RLOGD("backup success!!!\n"); |
| module->setCompleteBackup(module, current_slot); |
| } |
| } |
| else |
| { |
| RLOGD("Don't need backup\n"); |
| } |
| //xf.li@20230822 add for ab backup end |
| |
| return 0; |
| } |
| |
| int lynq_nand_open(const char *pathname, int flags) |
| { |
| // printf("pathname:%s---flags:%d",pathname,flags); |
| return open(pathname,flags); |
| } |
| |
| ssize_t lynq_nand_read(int fd, void *buf, size_t count) |
| { |
| // printf("rfd:%d---buf:%s---count:%d",fd,buf,count); |
| return read(fd,buf,count); |
| } |
| |
| ssize_t lynq_nand_write(int fd, void *buf, size_t count) |
| { |
| // printf("wfd:%d---buf:%s---count:%d",fd,buf,count); |
| return write(fd,buf,count); |
| } |
| |
| int lynq_nand_close(int fd) |
| { |
| return close(fd); |
| } |
| |
| /** |
| * @brief Obtain the upgrade result |
| * |
| * @param void |
| * @return 0xff:open file fail,0:upgrade success,1,upgrade wait |
| */ |
| int lynq_get_upgrade_status(void) |
| { |
| int lynq_state_fd; |
| int lynq_upgrade_wait = 1; |
| OTA_STATUS lynq_ota_status; |
| |
| memset(&lynq_ota_status, 0, sizeof(lynq_ota_status)); |
| |
| lynq_state_fd = open(FILE_FOTA_STATE,O_RDWR | O_CREAT,0777); |
| |
| if (lynq_state_fd < 0) |
| { |
| return 0xff; |
| } |
| read(lynq_state_fd,(unsigned char *)&lynq_ota_status,sizeof(lynq_ota_status)); |
| close(lynq_state_fd); |
| if((lynq_ota_status.ota_run != 0) && (lynq_ota_status.update_result == 0)) |
| { |
| return lynq_upgrade_wait; |
| } |
| return lynq_ota_status.update_result; |
| } |
| |
| /** |
| * @brief reboot device |
| * |
| * @param void |
| * @return void |
| */ |
| void lynq_reboot_device(void) |
| { |
| reboot_device(); |
| return ; |
| } |
| |
| /** |
| * @brief fota no resatrt |
| * |
| * @param void |
| * @return 0:fota success -Other values:fota fail |
| */ |
| |
| int lynq_fota_nrestart(void) |
| { |
| |
| int ret = 0; |
| #if 0 |
| printf("-********copy delta ***-\n"); |
| test_write_delta("/data/delta",DEV_DELTA); |
| #endif |
| |
| ret = rock_update_main(0, 0, 0, 0, 1, 1, 0, 1); |
| RLOGD("rock_update_nrestart ret = %d\n", ret); |
| if(ret) |
| { |
| RLOGD("fota update fail!\n"); |
| } |
| return ret; |
| } |
| |
| /** |
| * @brief Set the upgrade package address |
| * |
| * @param1 value:fota addr |
| * @param1 szie:fota addr length |
| * @return 0:set success other:set fail |
| */ |
| int lynq_fota_set_addr_value(char *value,int size) |
| { |
| if(size < 64) |
| { |
| return lynq_set_value(FOTA_UCI_MODULE,FOTA_UCI_ADDR, value); |
| } |
| return -1; |
| } |
| /** |
| * @brief get the upgrade package address |
| * |
| * @param1 value:fota addr |
| * @return 0:get success other:set fail |
| */ |
| int lynq_fota_get_addr_value(char *tmp) |
| { |
| return lynq_get_value(FOTA_UCI_FILE, FOTA_UCI_MODULE,FOTA_UCI_ADDR, tmp); |
| } |
| |
| /** |
| * @brief Porting wakes up the demo content |
| */ |
| static void lynq_init_wake_lock_func(void) |
| { |
| const char *lynqLibPath_WakeLock = "/usr/lib64/libpower.so"; |
| |
| dlHandle_wakelock = dlopen(lynqLibPath_WakeLock, RTLD_NOW); |
| if (dlHandle_wakelock == NULL) |
| { |
| printf("dlopen lynqLibPath_WakeLock failed: %s", dlerror()); |
| exit(EXIT_FAILURE); |
| } |
| |
| acquire_wake_lock = (int(*)(int,const char*))dlsym(dlHandle_wakelock, "acquire_wake_lock"); |
| if (acquire_wake_lock == NULL) { |
| printf("acquire_wake_lock not defined or exported in %s", lynqLibPath_WakeLock); |
| exit(EXIT_FAILURE); |
| } |
| release_wake_lock = (int(*)( const char*))dlsym(dlHandle_wakelock, "release_wake_lock"); |
| if (release_wake_lock == NULL) { |
| printf("release_wake_lock not defined or exported in %s", lynqLibPath_WakeLock); |
| exit(EXIT_FAILURE); |
| } |
| dlerror(); // Clear any previous dlerror |
| |
| return; |
| } |
| |
| /** |
| * @brief fota wake lock |
| * |
| * @param1 value:void |
| * @return ; |
| */ |
| static void lynq_fota_grab_artial_wake_lock(void) |
| { |
| acquire_wake_lock(PARTIAL_WAKE_LOCK, ANDROID_WAKE_LOCK_NAME); |
| } |
| |
| /** |
| * @brief get the upgrade package address |
| * |
| * @param1 value:void |
| * @return ; |
| */ |
| static void lynq_fota_release_wake_lock(void) |
| { |
| release_wake_lock(ANDROID_WAKE_LOCK_NAME); |
| } |
| /** |
| * @brief This is the wake up call |
| * end |
| */ |