blob: 894613e77778a62205c6e1ad05d81700a273fc71 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <assert.h>
#include "os/mynewt.h"
#include "bootutil/bootutil.h"
#include "bootutil/image.h"
#include "config/config.h"
#include "split/split.h"
#include "split_priv.h"
#define LOADER_IMAGE_SLOT 0
#define SPLIT_IMAGE_SLOT 1
#define SPLIT_TOTAL_IMAGES 2
static int8_t split_mode_cur;
static int8_t split_app_active;
void
split_app_init(void)
{
int rc;
/* Ensure this function only gets called by sysinit. */
SYSINIT_ASSERT_ACTIVE();
rc = split_conf_init();
assert(rc == 0);
}
split_status_t
split_check_status(void)
{
void *entry;
int rc;
rc = split_go(LOADER_IMAGE_SLOT, SPLIT_IMAGE_SLOT, &entry);
switch (rc) {
case SPLIT_GO_ERR:
return SPLIT_STATUS_INVALID;
case SPLIT_GO_NON_MATCHING:
return SPLIT_STATUS_NOT_MATCHING;
case SPLIT_GO_OK:
return SPLIT_STATUS_MATCHING;
default:
assert(0);
return SPLIT_STATUS_INVALID;
}
}
split_mode_t
split_mode_get(void)
{
return split_mode_cur;
}
int
split_app_active_get(void)
{
return split_app_active;
}
void
split_app_active_set(int active)
{
split_app_active = !!active;
}
int
split_mode_set(split_mode_t split_mode)
{
/* XXX: For now, cast this as an integer. This value should either be
* treated as an enumeration generally (i.e. not read directly and assigned
* from values in flash), or switched to a native type of integer. However,
* this is not a high priority change, so just cast it for now.
*/
if ((int) split_mode < 0 || (int) split_mode >= SPLIT_MODE_CNT) {
return SYS_EINVAL;
}
split_mode_cur = split_mode;
return 0;
}
/**
* This validates and provides the loader image data
*
* @return 0 on success; nonzero on failure.
*/
int
split_app_go(void **entry, int toboot)
{
split_mode_t split_mode;
int run_app;
int rc;
/* Make sure the configuration has been loaded. We need the persisted
* `split/status` value to proceed.
*/
conf_ensure_loaded();
if (toboot) {
split_mode = split_mode_get();
/* if we are told not to, then we don't boot an app */
if (split_mode == SPLIT_MODE_LOADER) {
return -1;
}
/* if this is a one-time test, reset the split mode */
switch (split_mode) {
case SPLIT_MODE_LOADER:
run_app = 0;
break;
case SPLIT_MODE_TEST_APP:
split_write_split(SPLIT_MODE_LOADER);
run_app = 1;
break;
case SPLIT_MODE_TEST_LOADER:
split_write_split(SPLIT_MODE_APP);
run_app = 0;
break;
case SPLIT_MODE_APP:
run_app = 1;
break;
default:
run_app = 0;
break;
}
if (!run_app) {
return -1;
}
}
rc = split_go(LOADER_IMAGE_SLOT, SPLIT_IMAGE_SLOT, entry);
if (rc != 0) {
/* Images don't match; clear split status. */
split_write_split(SPLIT_MODE_LOADER);
}
return rc;
}