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