120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi/* 220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * Copyright (C) 2015 Intel Corporation 320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * 420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * Licensed under the Apache License, Version 2.0 (the "License"); 520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * you may not use this file except in compliance with the License. 620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * You may obtain a copy of the License at 720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * 820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * http://www.apache.org/licenses/LICENSE-2.0 920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * 1020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * Unless required by applicable law or agreed to in writing, software 1120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * distributed under the License is distributed on an "AS IS" BASIS, 1220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * See the License for the specific language governing permissions and 1420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * limitations under the License. 1520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi */ 1620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 1720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi/* 1820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * Implementation of boot_control HAL as specified by google in 1920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * Brillo Development Platform Specification. Please refer to the 2020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * said document for more details. 2120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi */ 2220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 2320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 2420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi#include <errno.h> 2520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi#include <fcntl.h> 2620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi#include <unistd.h> 2720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi#include <stdio.h> 2820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi#include <stdlib.h> 2920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi#include <string.h> 3020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi#include <hardware/hardware.h> 3120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi#include <hardware/boot_control.h> 3220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 3320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi#include "bootctrl.h" 3420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 3520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi#define BOOTCTRL_METADATA_FILE "/dev/block/by-name/misc" 3620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi#define SLOT_SUFFIX_STR "androidboot.slot_suffix=" 3720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 3820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi#define COMMAND_LINE_SIZE 2048 3920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 4020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmistatic int bootctrl_read_metadata(boot_ctrl_t *bctrl) 4120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi{ 4220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi int fd, err; 4320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi ssize_t sz, size; 4420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi char *buf = (char *)bctrl; 4520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 4620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi fd = open(BOOTCTRL_METADATA_FILE, O_RDONLY); 4720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (fd < 0) { 4820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi err = errno; 4920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi fprintf(stderr, "Error opening metadata file: %s\n", strerror(errno)); 5020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return -err; 5120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 5220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (lseek(fd, OFFSETOF_SLOT_SUFFIX, SEEK_SET) < 0) { 5320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi err = errno; 5420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi fprintf(stderr, "Error seeking to metadata offset: %s\n", strerror(errno)); 5520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi close(fd); 5620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return -err; 5720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 5820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi size = sizeof(boot_ctrl_t); 5920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi do { 6020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi sz = read(fd, buf, size); 6120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (sz == 0) { 6220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi break; 6320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } else if (sz < 0) { 6420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (errno == EINTR) { 6520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi continue; 6620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 6720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi err = -errno; 6820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi fprintf(stderr, "Error reading metadata file\n"); 6920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi close(fd); 7020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return err; 7120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 7220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi size -= sz; 7320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi buf += sz; 7420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } while(size > 0); 7520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 7620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi close(fd); 7720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 7820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi /* Check if the data is correct */ 7920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (bctrl->magic != BOOTCTRL_MAGIC) { 8020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi fprintf(stderr, "metadata is not initialised or corrupted.\n"); 8120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return -EIO; 8220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 8320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return 0; 8420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi} 8520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 8620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmistatic int bootctrl_write_metadata(boot_ctrl_t *bctrl) 8720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi{ 8820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi int fd, err; 8920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi ssize_t sz, size; 9020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi char *buf = (char *)bctrl; 9120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 9220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi fd = open(BOOTCTRL_METADATA_FILE, O_RDWR); 9320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (fd < 0) { 9420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi err = errno; 9520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi fprintf(stderr, "Error opening metadata file: %s\n", strerror(errno)); 9620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return -err; 9720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 9820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 9920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (lseek(fd, OFFSETOF_SLOT_SUFFIX, SEEK_SET) < 0) { 10020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi err = errno; 10120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi fprintf(stderr, "Error seeking to metadata offset: %s\n", strerror(errno)); 10220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi close(fd); 10320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return -err; 10420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 10520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi size = sizeof(boot_ctrl_t); 10620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi do { 10720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi sz = write(fd, buf, size); 10820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (sz == 0) { 10920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi break; 11020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } else if (sz < 0) { 11120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (errno == EINTR) { 11220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi continue; 11320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 11420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi err = -errno; 11520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi fprintf(stderr, "Error Writing metadata file\n"); 11620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi close(fd); 11720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return err; 11820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 11920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi size -= sz; 12020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi buf += sz; 12120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } while(size > 0); 12220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 12320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi close(fd); 12420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return 0; 12520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi} 12620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 12720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmivoid bootctrl_init(boot_control_module_t *module __unused) 12820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi{ 12920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi /* Nothing to init */ 13020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi} 13120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 13220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmiunsigned bootctrl_get_number_slots(boot_control_module_t *module __unused) 13320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi{ 13420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi /* This is A/B system, so it will be always 2. */ 13520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return 2; 13620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi} 13720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 13820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmiint bootctrl_get_active_slot() 13920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi{ 14020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi int fd, err, slot; 14120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi ssize_t size = COMMAND_LINE_SIZE, sz; 14220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi off_t off; 14320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi char *buf, *ptr; 14420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi char *str; 14520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 14620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi fd = open("/proc/cmdline", O_RDONLY); 14720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (fd < 0) { 14820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi err = -errno; 14920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi fprintf(stderr, "error reading commandline\n"); 15020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return err; 15120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 15220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi ptr = buf = malloc(size); 15320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (!buf) { 15420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi err = -errno; 15520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi fprintf(stderr, "Error allocating memory\n"); 15620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi close(fd); 15720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return err; 15820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 15920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi do { 16020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi sz = read(fd, buf, size); 16120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (sz == 0) { 16220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi break; 16320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } else if (sz < 0) { 16420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (errno == EINTR) { 16520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi continue; 16620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 16720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi err = -errno; 16820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi fprintf(stderr, "Error reading file\n"); 16920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi free(ptr); 17020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi close(fd); 17120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return err; 17220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 17320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi size -= sz; 17420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi buf += sz; 17520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } while(size > 0); 17620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi str = strstr((char *)ptr, SLOT_SUFFIX_STR); 17720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (!str) { 17820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi err = -EIO; 17920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi fprintf(stderr, "cannot find %s in kernel commandline.\n", SLOT_SUFFIX_STR); 18020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi free(ptr); 18120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi close(fd); 18220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return err; 18320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 18420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi str += sizeof(SLOT_SUFFIX_STR); 18520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slot = (*str == 'a') ? 0 : 1; 18620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi free(ptr); 18720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi close(fd); 18820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 18920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return slot; 19020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi} 19120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 19220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmiunsigned bootctrl_get_current_slot(boot_control_module_t *module __unused) 19320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi{ 19420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi int ret; 19520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi boot_ctrl_t metadata; 19620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 19720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi ret = bootctrl_read_metadata(&metadata); 19820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (ret < 0) { 19920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi /* anything larger than 2 will be considered as error. */ 20020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return (unsigned)ret; 20120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 20220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 20320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return bootctrl_get_active_slot(); 20420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi} 20520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 20620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmiint bootctrl_mark_boot_successful(boot_control_module_t *module __unused) 20720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi{ 20820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi int ret, slot; 20920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi boot_ctrl_t metadata; 21020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slot_metadata_t *slotp; 21120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 21220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi ret = bootctrl_read_metadata(&metadata); 21320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (ret < 0) { 21420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return ret; 21520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 21620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 21720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi /* In markBootSuccessful(), set Successful Boot to 1 and 21820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * Tries Remaining to 0. 21920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi */ 22020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slot = bootctrl_get_active_slot(); 22120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (slot < 0) { 22220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return slot; 22320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 22420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slotp = &metadata.slot_info[slot]; 22520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slotp->successful_boot = 1; 22620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slotp->tries_remaining = 0; 22720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 22820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return bootctrl_write_metadata(&metadata); 22920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi} 23020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 23120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmiint bootctrl_set_active_boot_slot(boot_control_module_t *module __unused, 23220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi unsigned slot) 23320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi{ 23420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi int ret, slot2; 23520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi boot_ctrl_t metadata; 23620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slot_metadata_t *slotp; 23720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 23820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (slot >= 2) { 23920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi fprintf(stderr, "Wrong Slot value %u\n", slot); 24020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return -EINVAL; 24120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 24220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi ret = bootctrl_read_metadata(&metadata); 24320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (ret < 0) { 24420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return ret; 24520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 24620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 24720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi /* In setActiveBootSlot(), set Priority to 15, Tries Remaining to 7 and 24820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * Successful Boot to 0. Before doing this, lower priorities of other slots 24920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * so they are all less than 15 in a way that preserves existing priority 25020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * ordering. Calling setActiveBootSlot() on a slot that already has 25120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * Successful Boot set to 1 MUST not fail. 25220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi */ 25320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slotp = &metadata.slot_info[slot]; 25420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slotp->successful_boot = 0; 25520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slotp->priority = 15; 25620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slotp->tries_remaining = 7; 25720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 25820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slot2 = (slot == 0) ? 1 : 0; 25920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slotp = &metadata.slot_info[slot2]; 26020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (slotp->priority >= 15) { 26120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slotp->priority = 14; 26220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 26320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi ret = bootctrl_write_metadata(&metadata); 26420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (ret < 0) { 26520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return ret; 26620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 26720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 26820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return 0; 26920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi} 27020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 27120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmiint bootctrl_set_slot_as_unbootable(boot_control_module_t *module __unused, 27220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi unsigned slot) 27320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi{ 27420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi int ret; 27520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi boot_ctrl_t metadata; 27620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slot_metadata_t *slotp; 27720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 27820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (slot >= 2) { 27920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi fprintf(stderr, "Wrong Slot value %u\n", slot); 28020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return -EINVAL; 28120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 28220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi ret = bootctrl_read_metadata(&metadata); 28320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (ret < 0) { 28420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return ret; 28520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 28620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 28720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi /* In setSlotAsUnbootable(), set Priority, Tries Remaining and 28820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi * Successful Boot to 0. 28920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi */ 29020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slotp = &metadata.slot_info[slot]; 29120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slotp->successful_boot = 0; 29220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slotp->priority = 0; 29320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi slotp->tries_remaining = 0; 29420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi ret = bootctrl_write_metadata(&metadata); 29520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (ret < 0) { 29620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return ret; 29720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 29820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 29920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return 0; 30020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi} 30120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 30220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmiint bootctrl_is_slot_bootable(boot_control_module_t *module __unused, 30320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi unsigned slot) 30420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi{ 30520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi int ret; 30620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi boot_ctrl_t metadata; 30720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 30820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (slot >= 2) { 30920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi fprintf(stderr, "Wrong Slot value %u\n", slot); 31020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return -EINVAL; 31120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 31220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi ret = bootctrl_read_metadata(&metadata); 31320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (ret < 0) { 31420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return ret; 31520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi } 31620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 31720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return (metadata.slot_info[slot].priority != 0); 31820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi} 31920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 32020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmiconst char *bootctrl_get_suffix(boot_control_module_t *module __unused, 32120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi unsigned slot) 32220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi{ 32320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi static const char* suffix[2] = {BOOTCTRL_SUFFIX_A, BOOTCTRL_SUFFIX_B}; 32420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi if (slot >= 2) 32520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return NULL; 32620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return suffix[slot]; 32720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi} 32820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 32920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmistatic int bootctrl_open(const hw_module_t *module, const char *id __unused, 33020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi hw_device_t **device __unused) 33120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi{ 33220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi /* Nothing to do currently */ 33320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi return 0; 33420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi} 33520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 33620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmistatic struct hw_module_methods_t bootctrl_methods = { 33720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi .open = bootctrl_open, 33820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi}; 33920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 34020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi/* Boot Control Module implementation */ 34120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmiboot_control_module_t HAL_MODULE_INFO_SYM = { 34220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi .common = { 34320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi .tag = HARDWARE_MODULE_TAG, 34420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi .module_api_version = BOOT_CONTROL_MODULE_API_VERSION_0_1, 34520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi .hal_api_version = HARDWARE_HAL_API_VERSION, 34620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi .id = BOOT_CONTROL_HARDWARE_MODULE_ID, 34720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi .name = "boot_control HAL", 34820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi .author = "Intel Corporation", 34920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi .methods = &bootctrl_methods, 35020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi }, 35120b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi .init = bootctrl_init, 35220b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi .getNumberSlots = bootctrl_get_number_slots, 35320b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi .getCurrentSlot = bootctrl_get_current_slot, 35420b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi .markBootSuccessful = bootctrl_mark_boot_successful, 35520b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi .setActiveBootSlot = bootctrl_set_active_boot_slot, 35620b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi .setSlotAsUnbootable = bootctrl_set_slot_as_unbootable, 35720b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi .isSlotBootable = bootctrl_is_slot_bootable, 35820b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi .getSuffix = bootctrl_get_suffix, 35920b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi}; 36020b554f16dc6ee081d0952272d1f130e957d1600Manish Regmi 361