Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f89784a5 authored by Tianjie Xu's avatar Tianjie Xu Committed by Gerrit Code Review
Browse files

Merge "Move libboot_control to boot_control 1.1"

parents 93bba950 c971ea8d
Loading
Loading
Loading
Loading
+61 −0
Original line number Diff line number Diff line
//
// Copyright (C) 2018 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.
//

cc_defaults {
    name: "libboot_control_defaults",
    vendor: true,
    recovery_available: true,
    relative_install_path: "hw",

    cflags: [
        "-D_FILE_OFFSET_BITS=64",
        "-Werror",
        "-Wall",
        "-Wextra",
    ],

    shared_libs: [
        "android.hardware.boot@1.1",
        "libbase",
        "liblog",
    ],
    static_libs: [
        "libbootloader_message_vendor",
        "libfstab",
    ],
}

cc_library_static {
    name: "libboot_control",
    defaults: ["libboot_control_defaults"],
    export_include_dirs: ["include"],

    srcs: ["libboot_control.cpp"],
}

cc_library_shared {
    name: "bootctrl.default",
    defaults: ["libboot_control_defaults"],

    srcs: ["legacy_boot_control.cpp"],

    static_libs: [
        "libboot_control",
    ],
    shared_libs: [
        "libhardware",
    ],
}
+89 −0
Original line number Diff line number Diff line
//
// Copyright (C) 2019 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.
//

#pragma once

#include <string>

#include <android/hardware/boot/1.1/IBootControl.h>

namespace android {
namespace bootable {

// Helper library to implement the IBootControl HAL using the misc partition.
class BootControl {
  using MergeStatus = ::android::hardware::boot::V1_1::MergeStatus;

 public:
  bool Init();
  unsigned int GetNumberSlots();
  unsigned int GetCurrentSlot();
  bool MarkBootSuccessful();
  bool SetActiveBootSlot(unsigned int slot);
  bool SetSlotAsUnbootable(unsigned int slot);
  bool SetSlotBootable(unsigned int slot);
  bool IsSlotBootable(unsigned int slot);
  const char* GetSuffix(unsigned int slot);
  bool IsSlotMarkedSuccessful(unsigned int slot);
  bool SetSnapshotMergeStatus(MergeStatus status);
  MergeStatus GetSnapshotMergeStatus();

  bool IsValidSlot(unsigned int slot);

  const std::string& misc_device() const {
    return misc_device_;
  }

 private:
  // Whether this object was initialized with data from the bootloader message
  // that doesn't change until next reboot.
  bool initialized_ = false;

  // The path to the misc_device as reported in the fstab.
  std::string misc_device_;

  // The number of slots present on the device.
  unsigned int num_slots_ = 0;

  // The slot where we are running from.
  unsigned int current_slot_ = 0;
};

// Helper functions to write the Virtual A/B merge status message. These are
// separate because BootControl uses bootloader_control_ab in vendor space,
// whereas the Virtual A/B merge status is in system space. A HAL might not
// use bootloader_control_ab, but may want to use the AOSP method of maintaining
// the merge status.

// If the Virtual A/B message has not yet been initialized, then initialize it.
// This should be called when the BootControl HAL first loads.
//
// If the Virtual A/B message in misc was already initialized, true is returned.
// If initialization was attempted, but failed, false is returned, and the HAL
// should fail to load.
bool InitMiscVirtualAbMessageIfNeeded();

// Save the current merge status as well as the current slot.
bool SetMiscVirtualAbMergeStatus(unsigned int current_slot,
                                 android::hardware::boot::V1_1::MergeStatus status);

// Return the current merge status. If the saved status is SNAPSHOTTED but the
// slot hasn't changed, the status returned will be NONE.
bool GetMiscVirtualAbMergeStatus(unsigned int current_slot,
                                 android::hardware::boot::V1_1::MergeStatus* status);

}  // namespace bootable
}  // namespace android
+111 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.
 */


/**
 * The A/B-specific bootloader message structure (4-KiB).
 *
 * We separate A/B boot control metadata from the regular bootloader
 * message struct and keep it here. Everything that's A/B-specific
 * stays after struct bootloader_message, which belongs to the vendor
 * space of /misc partition. Also, the A/B-specific contents should be
 * managed by the A/B-bootloader or boot control HAL.
 *
 * The slot_suffix field is used for A/B implementations where the
 * bootloader does not set the androidboot.ro.boot.slot_suffix kernel
 * commandline parameter. This is used by fs_mgr to mount /system and
 * other partitions with the slotselect flag set in fstab. A/B
 * implementations are free to use all 32 bytes and may store private
 * data past the first NUL-byte in this field. It is encouraged, but
 * not mandatory, to use 'struct bootloader_control' described below.
 *
 * The update_channel field is used to store the Omaha update channel
 * if update_engine is compiled with Omaha support.
 */
struct bootloader_message_ab {
    struct bootloader_message message;
    char slot_suffix[32];
    char update_channel[128];

    // Round up the entire struct to 4096-byte.
    char reserved[1888];
};

/**
 * Be cautious about the struct size change, in case we put anything post
 * bootloader_message_ab struct (b/29159185).
 */
#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus)
static_assert(sizeof(struct bootloader_message_ab) == 4096,
              "struct bootloader_message_ab size changes");
#endif

#define BOOT_CTRL_MAGIC   0x42414342 /* Bootloader Control AB */
#define BOOT_CTRL_VERSION 1

struct slot_metadata {
    // Slot priority with 15 meaning highest priority, 1 lowest
    // priority and 0 the slot is unbootable.
    uint8_t priority : 4;
    // Number of times left attempting to boot this slot.
    uint8_t tries_remaining : 3;
    // 1 if this slot has booted successfully, 0 otherwise.
    uint8_t successful_boot : 1;
    // 1 if this slot is corrupted from a dm-verity corruption, 0
    // otherwise.
    uint8_t verity_corrupted : 1;
    // Reserved for further use.
    uint8_t reserved : 7;
} __attribute__((packed));

/* Bootloader Control AB
 *
 * This struct can be used to manage A/B metadata. It is designed to
 * be put in the 'slot_suffix' field of the 'bootloader_message'
 * structure described above. It is encouraged to use the
 * 'bootloader_control' structure to store the A/B metadata, but not
 * mandatory.
 */
struct bootloader_control {
    // NUL terminated active slot suffix.
    char slot_suffix[4];
    // Bootloader Control AB magic number (see BOOT_CTRL_MAGIC).
    uint32_t magic;
    // Version of struct being used (see BOOT_CTRL_VERSION).
    uint8_t version;
    // Number of slots being managed.
    uint8_t nb_slot : 3;
    // Number of times left attempting to boot recovery.
    uint8_t recovery_tries_remaining : 3;
    // Status of any pending snapshot merge of dynamic partitions.
    uint8_t merge_status : 3;
    // Ensure 4-bytes alignment for slot_info field.
    uint8_t reserved0[1];
    // Per-slot information.  Up to 4 slots.
    struct slot_metadata slot_info[4];
    // Reserved for further use.
    uint8_t reserved1[8];
    // CRC32 of all 28 bytes preceding this field (little endian
    // format).
    uint32_t crc32_le;
} __attribute__((packed));

#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus)
static_assert(sizeof(struct bootloader_control) ==
              sizeof(((struct bootloader_message_ab *)0)->slot_suffix),
              "struct bootloader_control has wrong size");
#endif
+115 −0
Original line number Diff line number Diff line
/*
 * 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 <string>

#include <hardware/boot_control.h>
#include <hardware/hardware.h>

#include <libboot_control/libboot_control.h>

using android::bootable::BootControl;

struct boot_control_private_t {
  // The base struct needs to be first in the list.
  boot_control_module_t base;

  BootControl impl;
};

namespace {

void BootControl_init(boot_control_module_t* module) {
  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
  impl.Init();
}

unsigned int BootControl_getNumberSlots(boot_control_module_t* module) {
  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
  return impl.GetNumberSlots();
}

unsigned int BootControl_getCurrentSlot(boot_control_module_t* module) {
  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
  return impl.GetCurrentSlot();
}

int BootControl_markBootSuccessful(boot_control_module_t* module) {
  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
  return impl.MarkBootSuccessful() ? 0 : -1;
}

int BootControl_setActiveBootSlot(boot_control_module_t* module, unsigned int slot) {
  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
  return impl.SetActiveBootSlot(slot) ? 0 : -1;
}

int BootControl_setSlotAsUnbootable(struct boot_control_module* module, unsigned int slot) {
  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
  return impl.SetSlotAsUnbootable(slot) ? 0 : -1;
}

int BootControl_isSlotBootable(struct boot_control_module* module, unsigned int slot) {
  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
  return impl.IsSlotBootable(slot) ? 0 : -1;
}

int BootControl_isSlotMarkedSuccessful(struct boot_control_module* module, unsigned int slot) {
  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
  return impl.IsSlotMarkedSuccessful(slot) ? 0 : -1;
}

const char* BootControl_getSuffix(boot_control_module_t* module, unsigned int slot) {
  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
  return impl.GetSuffix(slot);
}

static int BootControl_open(const hw_module_t* module __unused, const char* id __unused,
                            hw_device_t** device __unused) {
  /* Nothing to do currently. */
  return 0;
}

struct hw_module_methods_t BootControl_methods = {
  .open = BootControl_open,
};

}  // namespace

boot_control_private_t HAL_MODULE_INFO_SYM = {
  .base =
      {
          .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 = "AOSP reference bootctrl HAL",
                  .author = "The Android Open Source Project",
                  .methods = &BootControl_methods,
              },
          .init = BootControl_init,
          .getNumberSlots = BootControl_getNumberSlots,
          .getCurrentSlot = BootControl_getCurrentSlot,
          .markBootSuccessful = BootControl_markBootSuccessful,
          .setActiveBootSlot = BootControl_setActiveBootSlot,
          .setSlotAsUnbootable = BootControl_setSlotAsUnbootable,
          .isSlotBootable = BootControl_isSlotBootable,
          .getSuffix = BootControl_getSuffix,
          .isSlotMarkedSuccessful = BootControl_isSlotMarkedSuccessful,
      },
};
+425 −0

File added.

Preview size limit exceeded, changes collapsed.