Files
android_vendor_pawlet/hal/boot_control/rpi/BootControl.h
T
oxmc 8f33626a21 recovery: build as a separate on-demand image; A/B failsafe via tryboot
Recovery is no longer embedded in boot.img -- that forced recovery.img into
the vendor image size check and overflowed the padded 2GB vendor partition.
Instead:

- common.mk gates recovery with PRODUCT_BUILD_RECOVERY_IMAGE (default false),
  so the normal build never touches it. Build it on demand with the new
  `precovery` helper (PAWLET_BUILD_RECOVERY=1 m recoveryimage) and flash the
  result to the recovery partition.
- pawlet-recoveryboot.sh enters recovery via reboot,3 (separate partition)
  again, and gains a boot-loop failsafe: a /metadata counter (cleared on
  boot_completed via the .rc) drops the device into recovery after BOOT_MAX
  consecutive boots that reach early init but never complete.
- BootControl comments restored to A/B-via-tryboot (a failed trial reverts to
  the active slot; recovery is a separate partition via reboot,3).
2026-07-17 05:11:02 -07:00

67 lines
2.5 KiB
C++

/*
* Copyright (C) The Android Open Source Project
* Copyright (C) 2025 oxmc / PawletOS
*
* SPDX-License-Identifier: Apache-2.0
*
* Implements the AOSP android.hardware.boot AIDL interface
* (hardware/interfaces/boot/) for Raspberry Pi 4/5.
*/
#pragma once
#include <aidl/android/hardware/boot/BnBootControl.h>
#include <aidl/android/hardware/boot/MergeStatus.h>
#include "misc_rpi.h"
namespace aidl::android::hardware::boot {
/**
* PawletOS boot_control AIDL HAL for Raspberry Pi 4 / 5.
*
* Slot metadata is persisted in the "misc" GPT partition at
* PAWLET_MISC_OFFSET (see misc_rpi.h).
*
* The RPi firmware's tryboot mechanism is used for slot switching (a failed
* trial reverts to the active slot; recovery is a separate partition entered
* via reboot,3):
* setActiveBootSlot(1) — writes pending-B to misc
* (caller triggers `reboot tryboot` to boot boot_b for one attempt)
* markBootSuccessful() — confirms boot; if current slot is B, copies
* boot_b → boot_a to make the change permanent
*/
class BootControl : public BnBootControl {
public:
BootControl(const char* misc_device,
const char* boot_a_device,
const char* boot_b_device);
// IBootControl
ndk::ScopedAStatus getNumberSlots(int32_t* out) override;
ndk::ScopedAStatus getCurrentSlot(int32_t* out) override;
ndk::ScopedAStatus getActiveBootSlot(int32_t* out) override;
ndk::ScopedAStatus getSuffix(int32_t slot, std::string* out) override;
ndk::ScopedAStatus markBootSuccessful() override;
ndk::ScopedAStatus setActiveBootSlot(int32_t slot) override;
ndk::ScopedAStatus setSlotAsUnbootable(int32_t slot) override;
ndk::ScopedAStatus isSlotBootable(int32_t slot, bool* out) override;
ndk::ScopedAStatus isSlotMarkedSuccessful(int32_t slot, bool* out) override;
ndk::ScopedAStatus getSnapshotMergeStatus(MergeStatus* out) override;
ndk::ScopedAStatus setSnapshotMergeStatus(MergeStatus status) override;
private:
const std::string misc_device_;
const std::string boot_a_device_;
const std::string boot_b_device_;
bool readMisc(PawletBootControl* ctrl);
bool writeMisc(const PawletBootControl& ctrl);
void initDefaultMisc(PawletBootControl* ctrl);
bool copyBootPartition(const std::string& src, const std::string& dst);
static uint32_t computeCrc32(const void* data, size_t len);
static bool isValidSlot(int32_t slot);
};
} // namespace aidl::android::hardware::boot