1aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen/* 2aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen * Copyright (C) 2015 The Android Open Source Project 3aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen * 4aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen * Licensed under the Apache License, Version 2.0 (the "License"); 5aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen * you may not use this file except in compliance with the License. 6aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen * You may obtain a copy of the License at 7aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen * 8aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen * http://www.apache.org/licenses/LICENSE-2.0 9aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen * 10aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen * Unless required by applicable law or agreed to in writing, software 11aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen * distributed under the License is distributed on an "AS IS" BASIS, 12aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen * See the License for the specific language governing permissions and 14aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen * limitations under the License. 15aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen */ 16aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 17aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen#include <sys/types.h> 18aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen#include <sys/stat.h> 19aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen#include <unistd.h> 20aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen#include <fcntl.h> 21aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 22aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen#include <errno.h> 23aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen#include <inttypes.h> 24aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen#include <stdio.h> 25aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen#include <string.h> 26aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 27aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen#include <fs_mgr.h> 28aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen#include <hardware/hardware.h> 29aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen#include <hardware/boot_control.h> 30aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 31aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen#include "bootinfo.h" 32aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 33aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthenvoid module_init(boot_control_module_t *module) 34aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen{ 35aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen} 36aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 37aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthenunsigned module_getNumberSlots(boot_control_module_t *module) 38aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen{ 39aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return 2; 40aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen} 41aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 423af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthenstatic bool get_dev_t_for_partition(const char *name, dev_t *out_device) 433af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen{ 443af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen int fd; 453af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen struct stat statbuf; 463af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen 473af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen fd = boot_info_open_partition(name, NULL, O_RDONLY); 483af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen if (fd == -1) 493af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen return false; 503af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen if (fstat(fd, &statbuf) != 0) { 513af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen fprintf(stderr, "WARNING: Error getting information about part %s: %s\n", 523af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen name, strerror(errno)); 533af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen close(fd); 543af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen return false; 553af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen } 563af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen close(fd); 573af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen *out_device = statbuf.st_rdev; 583af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen return true; 593af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen} 603af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen 61aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthenunsigned module_getCurrentSlot(boot_control_module_t *module) 62aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen{ 633af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen struct stat statbuf; 643af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen dev_t system_a_dev, system_b_dev; 65aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 663af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen if (stat("/system", &statbuf) != 0) { 673af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen fprintf(stderr, "WARNING: Error getting information about /system: %s\n", 683af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen strerror(errno)); 693af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen return 0; 70aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 71aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 723af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen if (!get_dev_t_for_partition("system_a", &system_a_dev) || 733af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen !get_dev_t_for_partition("system_b", &system_b_dev)) 743af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen return 0; 753af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen 763af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen if (statbuf.st_dev == system_a_dev) { 773af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen return 0; 783af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen } else if (statbuf.st_dev == system_b_dev) { 793af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen return 1; 803af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen } else { 813af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen fprintf(stderr, "WARNING: Error determining current slot " 823af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen "(/system dev_t of %d:%d does not match a=%d:%d or b=%d:%d)\n", 833af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen major(statbuf.st_dev), minor(statbuf.st_dev), 843af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen major(system_a_dev), minor(system_a_dev), 853af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen major(system_b_dev), minor(system_b_dev)); 863af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen return 0; 873af8b53ae8cd70abaca17b7d9140ee12a14486b8David Zeuthen } 88aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen} 89aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 90aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthenint module_markBootSuccessful(boot_control_module_t *module) 91aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen{ 92aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return 0; 93aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen} 94aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 95aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen#define COPY_BUF_SIZE 1024*1024 96aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 97aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthenstatic bool copy_data(int src_fd, int dst_fd, size_t num_bytes) 98aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen{ 99aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen char copy_buf[COPY_BUF_SIZE]; 100aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen size_t remaining; 101aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 102aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen remaining = num_bytes; 103aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen while (remaining > 0) { 104aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen size_t num_to_read = remaining > COPY_BUF_SIZE ? COPY_BUF_SIZE : remaining; 105aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen ssize_t num_read; 106aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen do { 107aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen num_read = read(src_fd, copy_buf, num_to_read); 108aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } while (num_read == -1 && errno == EINTR); 109aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (num_read <= 0) { 110aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen fprintf(stderr, "Error reading %zd bytes from source: %s\n", 111aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen num_to_read, strerror(errno)); 112aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return false; 113aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 114aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen size_t num_to_write = num_read; 115aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen while (num_to_write > 0) { 116aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen size_t offset = num_read - num_to_write; 117aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen ssize_t num_written; 118aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen do { 119aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen num_written = write(dst_fd, copy_buf + offset, num_to_write); 120aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } while (num_written == -1 && errno == EINTR); 121aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (num_written <= 0) { 122aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen fprintf(stderr, "Error writing %zd bytes to destination: %s\n", 123aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen num_to_write, strerror(errno)); 124aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return false; 125aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 126aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen num_to_write -= num_written; 127aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 128aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen remaining -= num_read; 129aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 130aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 131aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return true; 132aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen} 133aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 134aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthenint module_setActiveBootSlot(boot_control_module_t *module, unsigned slot) 135aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen{ 136aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen BrilloBootInfo info; 137aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen int src_fd, dst_fd; 138aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen uint64_t src_size, dst_size; 139aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen char src_name[32]; 140aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 141aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (slot >= 2) 142aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return -EINVAL; 143aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 144aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (!boot_info_load(&info)) { 145aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen fprintf(stderr, "WARNING: Error loading boot-info. Resetting.\n"); 146aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen boot_info_reset(&info); 147aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } else { 148aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (!boot_info_validate(&info)) { 149aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen fprintf(stderr, "WARNING: boot-info is invalid. Resetting.\n"); 150aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen boot_info_reset(&info); 151aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 152aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 153aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 154aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen info.active_slot = slot; 155aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen info.slot_info[slot].bootable = true; 156aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen snprintf(info.bootctrl_suffix, 157aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen sizeof(info.bootctrl_suffix), 158aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen "_%c", slot + 'a'); 159aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 160aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (!boot_info_save(&info)) { 161aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen fprintf(stderr, "Error saving boot-info.\n"); 162aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return -errno; 163aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 164aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 165aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen // Finally copy the contents of boot_X into boot. 166aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen snprintf(src_name, sizeof(src_name), "boot_%c", slot + 'a'); 167aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen src_fd = boot_info_open_partition(src_name, &src_size, O_RDONLY); 168aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (src_fd == -1) { 169aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen fprintf(stderr, "Error opening \"%s\" partition.\n", src_name); 170aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return -errno; 171aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 172aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 173aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen dst_fd = boot_info_open_partition("boot", &dst_size, O_RDWR); 174aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (dst_fd == -1) { 175aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen fprintf(stderr, "Error opening \"boot\" partition.\n"); 176aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen close(src_fd); 177aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return -errno; 178aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 179aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 180aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (src_size != dst_size) { 181aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen fprintf(stderr, 182aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen "src (%" PRIu64 " bytes) and dst (%" PRIu64 " bytes) " 183aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen "have different sizes.\n", 184aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen src_size, dst_size); 185aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen close(src_fd); 186aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen close(dst_fd); 187aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return -EINVAL; 188aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 189aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 190aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (!copy_data(src_fd, dst_fd, src_size)) { 191aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen close(src_fd); 192aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen close(dst_fd); 193aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return -errno; 194aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 195aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 196aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (fsync(dst_fd) != 0) { 197aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen fprintf(stderr, "Error calling fsync on destination: %s\n", 198aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen strerror(errno)); 199aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return -errno; 200aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 201aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 202aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen close(src_fd); 203aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen close(dst_fd); 204aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return 0; 205aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen} 206aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 207aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthenint module_setSlotAsUnbootable(struct boot_control_module *module, unsigned slot) 208aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen{ 209aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen BrilloBootInfo info; 210aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 211aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (slot >= 2) 212aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return -EINVAL; 213aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 214aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (!boot_info_load(&info)) { 215aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen fprintf(stderr, "WARNING: Error loading boot-info. Resetting.\n"); 216aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen boot_info_reset(&info); 217aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } else { 218aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (!boot_info_validate(&info)) { 219aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen fprintf(stderr, "WARNING: boot-info is invalid. Resetting.\n"); 220aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen boot_info_reset(&info); 221aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 222aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 223aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 224aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen info.slot_info[slot].bootable = false; 225aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 226aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (!boot_info_save(&info)) { 227aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen fprintf(stderr, "Error saving boot-info.\n"); 228aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return -errno; 229aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 230aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 231aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return 0; 232aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen} 233aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 234aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthenint module_isSlotBootable(struct boot_control_module *module, unsigned slot) 235aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen{ 236aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen BrilloBootInfo info; 237aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 238aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (slot >= 2) 239aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return -EINVAL; 240aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 241aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (!boot_info_load(&info)) { 242aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen fprintf(stderr, "WARNING: Error loading boot-info. Resetting.\n"); 243aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen boot_info_reset(&info); 244aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } else { 245aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (!boot_info_validate(&info)) { 246aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen fprintf(stderr, "WARNING: boot-info is invalid. Resetting.\n"); 247aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen boot_info_reset(&info); 248aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 249aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen } 250aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 251aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return info.slot_info[slot].bootable; 252aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen} 253aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 254aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthenconst char* module_getSuffix(boot_control_module_t *module, unsigned slot) 255aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen{ 256aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen static const char* suffix[2] = {"_a", "_b"}; 257aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen if (slot >= 2) 258aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return NULL; 259aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen return suffix[slot]; 260aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen} 261aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 262aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthenstatic struct hw_module_methods_t module_methods = { 263aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen .open = NULL, 264aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen}; 265aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 266aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 267aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen/* This boot_control HAL implementation emulates A/B by copying the 268aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen * contents of the boot partition of the requested slot to the boot 269aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen * partition. It hence works with bootloaders that are not yet aware 270aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen * of A/B. This code is only intended to be used for development. 271aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen */ 272aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen 273aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthenboot_control_module_t HAL_MODULE_INFO_SYM = { 274aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen .common = { 275aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen .tag = HARDWARE_MODULE_TAG, 276aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen .module_api_version = BOOT_CONTROL_MODULE_API_VERSION_0_1, 277aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen .hal_api_version = HARDWARE_HAL_API_VERSION, 278aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen .id = BOOT_CONTROL_HARDWARE_MODULE_ID, 279aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen .name = "Copy Implementation of boot_control HAL", 280aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen .author = "The Android Open Source Project", 281aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen .methods = &module_methods, 282aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen }, 283aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen .init = module_init, 284aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen .getNumberSlots = module_getNumberSlots, 285aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen .getCurrentSlot = module_getCurrentSlot, 286aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen .markBootSuccessful = module_markBootSuccessful, 287aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen .setActiveBootSlot = module_setActiveBootSlot, 288aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen .setSlotAsUnbootable = module_setSlotAsUnbootable, 289aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen .isSlotBootable = module_isSlotBootable, 290aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen .getSuffix = module_getSuffix, 291aaa6282361272d3f5d10867245e1e489bd9d19f6David Zeuthen}; 292