Adds the full vendor/pawlet tree for PawletOS on Raspberry Pi 4/5: - build/: envsetup.sh helpers (breakfast/brunch/mka), bacon OTA target, Soong namespace, build core hook - config/: common.mk, version.mk, BoardConfigPawlet.mk, BoardConfigSoong.mk, privapp-permissions, me.pawlet.android feature XML - hal/boot_control/rpi/: AIDL boot_control HAL for RPi A/B slot switching - apps/Updater/: A/B OTA updater (download, verify, install, reboot) - apps/PawletPlatform/: platform resource APK (device icons, strings) - overlay/frameworks/base/core/res/: framework config overrides - prebuilt/, vars/: init rc, aosp_target_release
61 lines
2.3 KiB
C
61 lines
2.3 KiB
C
/*
|
||
* Copyright (C) The Android Open Source Project
|
||
* Copyright (C) 2025 oxmc / PawletOS
|
||
*
|
||
* SPDX-License-Identifier: Apache-2.0
|
||
*
|
||
* On-disk metadata format for PawletOS A/B boot control.
|
||
*
|
||
* Layout in the misc partition (4 MB, GPT label "misc"):
|
||
* 0x0000 – 0x07FF Android Bootloader Control Block (BCB) — do NOT touch
|
||
* 0x0800 – 0x0FFF Unused padding
|
||
* 0x1000 (4096) PawletBootControl — read/written by this HAL
|
||
*
|
||
* Slot numbering: 0 = slot A (boot_a, cmdline: androidboot.slot_suffix=_a)
|
||
* 1 = slot B (boot_b, cmdline: androidboot.slot_suffix=_b)
|
||
*
|
||
* A/B boot flow on RPi:
|
||
* - Normal boot always loads boot_a (GPT partition 1) via the RPi firmware.
|
||
* - To boot slot B once: `reboot tryboot` causes firmware to use
|
||
* boot_partition=2 for one attempt (see [tryboot] in config.txt).
|
||
* - On a confirmed-successful boot from slot B, markBootSuccessful() copies
|
||
* boot_b → boot_a so that subsequent normal reboots use the new content.
|
||
*/
|
||
#pragma once
|
||
|
||
#include <stdint.h>
|
||
#include <string.h>
|
||
|
||
// Magic value: "PAWL" in little-endian ASCII.
|
||
static constexpr uint32_t PAWLET_MAGIC = 0x4C574150u;
|
||
static constexpr uint32_t PAWLET_VERSION = 1u;
|
||
|
||
// Byte offset inside the misc partition where our struct lives.
|
||
static constexpr off_t PAWLET_MISC_OFFSET = 4096;
|
||
|
||
// How many boot attempts to grant a freshly-activated slot.
|
||
static constexpr int PAWLET_MAX_BOOT_ATTEMPTS = 3;
|
||
|
||
// Per-slot metadata (4 bytes).
|
||
struct PawletSlot {
|
||
uint8_t priority; // 0–15. Higher = preferred. 0 = unbootable.
|
||
uint8_t tries_remaining; // Remaining attempts before slot is unbootable.
|
||
uint8_t successful_boot; // 1 once markBootSuccessful() has been called.
|
||
uint8_t reserved;
|
||
};
|
||
|
||
// Complete on-disk structure placed at PAWLET_MISC_OFFSET.
|
||
// Total size: 24 bytes.
|
||
struct __attribute__((packed)) PawletBootControl {
|
||
uint32_t magic; // PAWLET_MAGIC
|
||
uint32_t version; // PAWLET_VERSION
|
||
uint8_t active_slot; // 0 = A, 1 = B
|
||
uint8_t merge_status; // android.hardware.boot.MergeStatus enum value
|
||
uint8_t reserved[2];
|
||
PawletSlot slots[2]; // [0] = slot A, [1] = slot B
|
||
uint32_t crc32; // CRC32 over all preceding bytes
|
||
};
|
||
|
||
static_assert(sizeof(PawletBootControl) == 24,
|
||
"PawletBootControl layout changed – update tests and partition docs");
|