diff options
Diffstat (limited to 'soc/common/boot_control/boot_control.c')
-rw-r--r-- | soc/common/boot_control/boot_control.c | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/soc/common/boot_control/boot_control.c b/soc/common/boot_control/boot_control.c new file mode 100644 index 0000000..fe40373 --- /dev/null +++ b/soc/common/boot_control/boot_control.c @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed 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 <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> + +#include <errno.h> +#include <inttypes.h> +#include <stdio.h> +#include <string.h> + +#include <fs_mgr.h> +#include <hardware/hardware.h> +#include <hardware/boot_control.h> +#include <cutils/properties.h> + +#include "bootinfo.h" + + +void boot_control_init(struct boot_control_module *module) +{ + return; +} + +unsigned get_number_slots(struct boot_control_module *module) +{ + return 2; +} + +unsigned get_current_slot(struct boot_control_module *module) +{ + char propbuf[PROPERTY_VALUE_MAX]; + const char* suffix[2] = {"_a", "_b"}; + int i; + + property_get("ro.boot.slot_suffix", propbuf, ""); + + if (propbuf[0] != '\0') { + for (i = 0; i < 2; i++) { + if (strncmp(propbuf, suffix[i], 2) == 0) + return i; + } + + if (i == 2) + fprintf(stderr, "WARNING: androidboot.slot_suffix is invalid\n"); + } else { + fprintf(stderr, "WARNING: androidboot.slot_suffix is NULL\n"); + } + + return 0; +} + +int mark_boot_successful(struct boot_control_module *module) +{ + BrilloBootInfo info; + unsigned current_slot; + int i; + + if (!boot_info_load(&info)) { + fprintf(stderr, "WARNING: Error loading boot-info. Resetting.\n"); + boot_info_reset(&info); + } else { + if (!boot_info_validate(&info)) { + fprintf(stderr, "WARNING: boot-info is invalid. Resetting.\n"); + boot_info_reset(&info); + } + } + + current_slot = get_current_slot(module); + + info.slot_info[current_slot].boot_successful = true; + info.slot_info[current_slot].tries_remaining = 0; + + if (!boot_info_save(&info)) { + fprintf(stderr, "WARNING: Error saving boot-info.\n"); + return -errno; + } + + return 0; +} + +int set_active_boot_slot(struct boot_control_module *module, unsigned slot) +{ + BrilloBootInfo info; + unsigned other_slot; + int i; + + if (slot >= 2) + return -EINVAL; + + if (!boot_info_load(&info)) { + fprintf(stderr, "WARNING: Error loading boot-info. Resetting.\n"); + boot_info_reset(&info); + } else { + if (!boot_info_validate(&info)) { + fprintf(stderr, "WARNING: boot-info is invalid. Resetting.\n"); + boot_info_reset(&info); + } + } + + other_slot = 1 - slot; + if (info.slot_info[other_slot].priority == 15) + info.slot_info[other_slot].priority = 14; + + info.slot_info[slot].bootable = true; + info.slot_info[slot].priority = 15; + info.slot_info[slot].tries_remaining = 7; + info.slot_info[slot].boot_successful = false; + + if (!boot_info_save(&info)) { + fprintf(stderr, "WARNING: Error saving boot-info.\n"); + return -errno; + } + + return 0; +} + +int set_slot_as_unbootable(struct boot_control_module *module, unsigned slot) +{ + BrilloBootInfo info; + + if (slot >= 2) + return -EINVAL; + + if (!boot_info_load(&info)) { + fprintf(stderr, "WARNING: Error loading boot-info. Resetting.\n"); + boot_info_reset(&info); + } else { + if (!boot_info_validate(&info)) { + fprintf(stderr, "WARNING: boot-info is invalid. Resetting.\n"); + boot_info_reset(&info); + } + } + + info.slot_info[slot].bootable = false; + info.slot_info[slot].priority = 0; + info.slot_info[slot].tries_remaining = 0; + info.slot_info[slot].boot_successful = false; + + if (!boot_info_save(&info)) { + fprintf(stderr, "WARNING: Error saving boot-info.\n"); + return -errno; + } + + return 0; +} + +int is_slot_bootable(struct boot_control_module *module, unsigned slot) +{ + BrilloBootInfo info; + + if (slot >= 2) + return -EINVAL; + + if (!boot_info_load(&info)) { + fprintf(stderr, "WARNING: Error loading boot-info. Resetting.\n"); + boot_info_reset(&info); + } else { + if (!boot_info_validate(&info)) { + fprintf(stderr, "WARNING: boot-info is invalid. Resetting.\n"); + boot_info_reset(&info); + } + } + + return info.slot_info[slot].bootable; +} + +const char* get_suffix(struct boot_control_module *module, unsigned slot) +{ + static const char* suffix[2] = {"_a", "_b"}; + + if (slot >= 2) + return NULL; + + return suffix[slot]; +} + +static struct hw_module_methods_t boot_control_module_methods = { + .open = NULL, +}; + +struct boot_control_module HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = BOOT_CONTROL_MODULE_API_VERSION_0_1, + .hal_api_version = HARDWARE_HAL_API_VERSION, + .id = BOOT_CONTROL_HARDWARE_MODULE_ID, + .name = "Marvell Boot Control HAL", + .author = "Marvell SEEDS", + .methods = &boot_control_module_methods, + }, + + .init = boot_control_init, + .getNumberSlots = get_number_slots, + .getCurrentSlot = get_current_slot, + .markBootSuccessful = mark_boot_successful, + .setActiveBootSlot = set_active_boot_slot, + .setSlotAsUnbootable = set_slot_as_unbootable, + .isSlotBootable = is_slot_bootable, + .getSuffix = get_suffix, +}; |