| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 | /* * Copyright (c) 2012-2014 Wind River Systems, Inc. * * SPDX-License-Identifier: Apache-2.0 */#include <kernel.h>#include <string.h>#include <drivers/nvram_config.h>#include <partition/partition.h>#include "ota_manifest.h"#include "ota_breakpoint.h"#include <os_common_api.h>#include <ota_storage.h>#ifdef CONFIG_WATCHDOG#include <watchdog_hal.h>#endifvoid ota_breakpoint_dump(struct ota_breakpoint *bp){#if CONFIG_SYS_LOG_DEFAULT_LEVEL > 2	struct ota_file *cur_file = &bp->cur_file;	int i;	SYS_LOG_INF("breakpoint: %p", bp);	SYS_LOG_INF("  old_version 0x%x, new_version 0x%x, data_checksum 0x%x",		bp->old_version, bp->new_version, bp->data_checksum);	SYS_LOG_INF("  bp_id %d, state %d, backend_type %d",		bp->bp_id, bp->state, bp->backend_type);	for (i = 0; i < ARRAY_SIZE(bp->file_state); i++) {		SYS_LOG_INF("  [%d] file_id %d state 0x%x", i,			bp->file_state[i].file_id, bp->file_state[i].state);	}	SYS_LOG_INF("  cur file %s: file_id %d, offset 0x%x, size 0x%x(0x%x)",		cur_file->name, cur_file->file_id, cur_file->offset, cur_file->size, cur_file->orig_size);	SYS_LOG_INF("  write_offset 0x%x(0x%x)\n",		bp->cur_file_write_offset, bp->cur_orig_write_offset);#endif}int ota_breakpoint_save(struct ota_breakpoint *bp){	int err;	SYS_LOG_INF("save bp: state %d\n", bp->state);	/* update seq id */	bp->bp_id++;	ota_breakpoint_dump(bp);	err = nvram_config_set("OTA_BP", bp, sizeof(struct ota_breakpoint));	if (err) {		return -1;	}	return 0;}int ota_breakpoint_file_state(struct ota_breakpoint *bp){	int err;	SYS_LOG_INF("save bp: state %d\n", bp->state);	/* update seq id */	bp->bp_id++;	ota_breakpoint_dump(bp);	err = nvram_config_set("OTA_BP", bp, sizeof(struct ota_breakpoint));	if (err) {		return -1;	}	return 0;}int ota_breakpoint_load(struct ota_breakpoint *bp){	int rlen;	SYS_LOG_INF("save bp: state %d\n", bp->state);	rlen = nvram_config_get("OTA_BP", bp, sizeof(struct ota_breakpoint));	if (rlen < 0) {		SYS_LOG_INF("cannot found OTA_BP");		return -1;	}	ota_breakpoint_dump(bp);	return 0;}int ota_breakpoint_get_current_state(struct ota_breakpoint *bp){	return bp->state;}int ota_breakpoint_set_file_state(struct ota_breakpoint *bp, int file_id, int state){	int i;	for (i = 0; i < ARRAY_SIZE(bp->file_state); i++) {		if (bp->file_state[i].file_id == file_id) {			//SYS_LOG_INF("set file_id %d file state 0x%x\n", file_id, state);			bp->file_state[i].state = state;			return 0;		}	}	/* not found, allocate new slot for this file */	for (i = 0; i < ARRAY_SIZE(bp->file_state); i++) {		if (bp->file_state[i].file_id == 0) {			//SYS_LOG_INF("set file_id %d file state 0x%x\n", file_id, state);			bp->file_state[i].file_id = file_id;			bp->file_state[i].state = state;			return 0;		}	}	/* no slot? */	SYS_LOG_INF("cannot found state slot for file_id %d\n", file_id);	return -1;}int ota_breakpoint_get_file_state(struct ota_breakpoint *bp, int file_id){	int i;	for (i = 0; i < ARRAY_SIZE(bp->file_state); i++) {		if (bp->file_state[i].file_id == file_id) {			return bp->file_state[i].state;		}	}	/* no slot? */	SYS_LOG_INF("cannot found state slot of file_id %d\n", file_id);	return -1;}int ota_breakpoint_clear_all_file_state(struct ota_breakpoint *bp){	int i;	SYS_LOG_INF("clear all file state");	for (i = 0; i < ARRAY_SIZE(bp->file_state); i++) {		bp->file_state[i].file_id = 0;		bp->file_state[i].state = 0;	}	memset(&bp->cur_file, 0x0, sizeof(struct ota_file));	bp->cur_file_write_offset = 0;	bp->cur_orig_write_offset = 0;	return 0;}int ota_breakpoint_update_state(struct ota_breakpoint *bp, int state){	SYS_LOG_INF("update breakpoint state %d", state);	bp->state = state;	if (state == OTA_BP_STATE_UPGRADE_DONE ||	    state == OTA_BP_STATE_UPGRADE_PENDING) {		ota_breakpoint_clear_all_file_state(bp);	}	ota_breakpoint_save(bp);	return 0;}extern struct ota_storage *ota_upgrade_storage_fine(struct ota_file *file);int ota_breakpoint_update_file_state(struct ota_breakpoint *bp, struct ota_file *file,		int state, int cur_file_offset, int cur_orig_offset, int force){	int need_save;	SYS_LOG_DBG("update bp file_id %d state %d offs 0x%x(0x%x)",		file->file_id, state, cur_file_offset, cur_orig_offset);	need_save = 0;	/* aligned with erase sector */	switch (state) {	case OTA_BP_FILE_STATE_WRITE_START:		memcpy(&bp->cur_file, file, sizeof(struct ota_file));		bp->cur_file_write_offset = cur_file_offset;		bp->cur_orig_write_offset = cur_orig_offset;		break;	case OTA_BP_FILE_STATE_WRITING:		if (force || (cur_orig_offset - bp->cur_orig_write_offset) == 0 ||		    (cur_orig_offset - bp->cur_orig_write_offset) >= OTA_BP_SAVE_SIZE) {			need_save = 1;			bp->cur_file_write_offset = cur_file_offset;			bp->cur_orig_write_offset = cur_orig_offset;		}		break;	default:		need_save = 1;		break;	}	ota_breakpoint_set_file_state(bp, file->file_id, state);	if (need_save){		ota_storage_sync(ota_upgrade_storage_fine(file));		ota_breakpoint_save(bp);#ifdef CONFIG_WATCHDOG		watchdog_clear();#endif	}	return 0;}int ota_breakpoint_init_default_value(struct ota_breakpoint *bp){	memset(bp, 0x0, sizeof(struct ota_breakpoint));	bp->old_version = fw_version_get_code();	bp->mirror_id = !partition_get_current_mirror_id();	bp->state = OTA_BP_STATE_UNKOWN;	return 0;}int ota_breakpoint_init(struct ota_breakpoint *bp){	int err;	SYS_LOG_INF("init bp %p\n", bp);	err = ota_breakpoint_load(bp);	if (err) {		SYS_LOG_INF("no bp in nvram, use default bp");		ota_breakpoint_init_default_value(bp);		ota_breakpoint_save(bp);	}	return 0;}void ota_breakpoint_exit(struct ota_breakpoint *bp){	SYS_LOG_INF("deinit bp %p\n", bp);}
 |