8f33626a21
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).
233 lines
7.9 KiB
Bash
233 lines
7.9 KiB
Bash
#!/bin/bash
|
|
#
|
|
# Copyright (C) 2012 The CyanogenMod Project
|
|
# Copyright (C) 2017 The LineageOS Project
|
|
# Copyright (C) 2025 oxmc / PawletOS
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
# PawletOS build environment helpers.
|
|
# Adapted from vendor/lineage/build/envsetup.sh (The LineageOS Project).
|
|
#
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# mka — invoke the Android build system
|
|
# ---------------------------------------------------------------------------
|
|
function mka()
|
|
{
|
|
m "$@"
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# cmka — clean + build a specific target
|
|
# ---------------------------------------------------------------------------
|
|
function cmka()
|
|
{
|
|
if [ ! -z "$1" ]; then
|
|
for i in "$@"; do
|
|
case $i in
|
|
bacon|otapackage|systemimage)
|
|
mka installclean
|
|
mka $i
|
|
;;
|
|
*)
|
|
mka clean-$i
|
|
mka $i
|
|
;;
|
|
esac
|
|
done
|
|
else
|
|
mka clean
|
|
mka
|
|
fi
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# cout — cd to the output directory
|
|
# ---------------------------------------------------------------------------
|
|
function cout()
|
|
{
|
|
if [ "$OUT" ]; then
|
|
cd $OUT
|
|
else
|
|
echo "Couldn't locate out directory. Try setting OUT."
|
|
fi
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# breakfast <device> [variant] — configure build for a PawletOS device
|
|
# ---------------------------------------------------------------------------
|
|
function breakfast()
|
|
{
|
|
local target=$1
|
|
local variant=$2
|
|
# Use gettop, not ANDROID_BUILD_TOP: the latter is only exported by lunch,
|
|
# so it is empty on the first breakfast (before any lunch) and the source
|
|
# path would collapse to /vendor/... and fail, leaving the release empty.
|
|
source $(gettop)/vendor/pawlet/vars/aosp_target_release
|
|
|
|
if [ $# -eq 0 ]; then
|
|
lunch
|
|
else
|
|
if [[ "$target" =~ -(user|userdebug|eng)$ ]]; then
|
|
lunch $target
|
|
else
|
|
if [ -z "$variant" ]; then
|
|
variant="userdebug"
|
|
fi
|
|
lunch pawlet_${target}-${aosp_target_release}-${variant}
|
|
fi
|
|
fi
|
|
return $?
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# brunch <device> — breakfast + make bacon
|
|
# ---------------------------------------------------------------------------
|
|
function brunch()
|
|
{
|
|
breakfast $*
|
|
if [ $? -eq 0 ]; then
|
|
mka bacon
|
|
else
|
|
echo "No such item in brunch menu. Try 'breakfast'"
|
|
return 1
|
|
fi
|
|
return $?
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# pawlet_version — print current version info
|
|
# ---------------------------------------------------------------------------
|
|
function pawlet_version()
|
|
{
|
|
local ver=$(get_build_var PAWLET_VERSION 2>/dev/null)
|
|
local type=$(get_build_var PAWLET_BUILDTYPE 2>/dev/null)
|
|
echo "PawletOS ${ver:-unknown} (${type:-UNOFFICIAL})"
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# pbuild — build the standard PawletOS partition images
|
|
# pbuild → boot + system + system_ext + vendor + product, all cores
|
|
# pbuild -j8 → same with custom parallelism
|
|
# ---------------------------------------------------------------------------
|
|
function pbuild()
|
|
{
|
|
m bootimage systemimage systemextimage vendorimage productimage -j$(nproc) "$@"
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# pdist — build the dist target, producing a target_files zip for signing
|
|
# ---------------------------------------------------------------------------
|
|
function pdist()
|
|
{
|
|
m dist -j$(nproc) "$@"
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# precovery — build the recovery image on its own
|
|
# Recovery is kept out of normal builds (see PRODUCT_BUILD_RECOVERY_IMAGE in
|
|
# common.mk). This flips it on just for this invocation and builds only the
|
|
# recovery image; flash the result to the recovery partition manually.
|
|
# Note: toggling recovery changes the product config, so this (and the next
|
|
# normal build) trigger a config re-analysis.
|
|
# ---------------------------------------------------------------------------
|
|
function precovery()
|
|
{
|
|
PAWLET_BUILD_RECOVERY=1 m recoveryimage "$@"
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# psign — sign a target_files zip with PawletOS release keys
|
|
# psign → auto-detects latest zip in dist/
|
|
# psign input.zip → sign specific zip → signed-target_files.zip
|
|
# psign input.zip output.zip → explicit input and output
|
|
# psign -c <certs-dir> ... → explicit certificate directory
|
|
#
|
|
# The release-key directory comes from the -c flag or the PAWLET_CERTS_DIR
|
|
# environment variable — there is no default path.
|
|
# Presigned microG/FDroid APKs are excluded from re-signing automatically.
|
|
# ---------------------------------------------------------------------------
|
|
function psign()
|
|
{
|
|
local T=$(gettop)
|
|
local certs="${PAWLET_CERTS_DIR}"
|
|
if [ "$1" = "-c" ]; then
|
|
certs=$2
|
|
shift 2
|
|
fi
|
|
local distdir="${DIST_DIR:-${OUT_DIR:-out}/dist}"
|
|
local input="${1:-$(ls -t "${distdir}"/*-target_files-*.zip 2>/dev/null | head -1)}"
|
|
local output="${2:-signed-target_files.zip}"
|
|
|
|
if [ -z "$certs" ] || [ ! -d "$certs" ]; then
|
|
echo "psign: no certs dir${certs:+ at '$certs'} — pass -c <dir> or set PAWLET_CERTS_DIR." >&2
|
|
return 1
|
|
fi
|
|
if [ -z "$input" ] || [ ! -f "$input" ]; then
|
|
echo "psign: no target_files zip found — run pdist first, or pass the path explicitly." >&2
|
|
return 1
|
|
fi
|
|
|
|
echo "psign: signing $input → $output (keys: $certs)"
|
|
"${T}/build/make/tools/releasetools/sign_target_files_apks" \
|
|
-o \
|
|
--default_key_mappings "$certs" \
|
|
--extra_apks GmsCore= \
|
|
--extra_apks GsfProxy= \
|
|
--extra_apks FakeStore= \
|
|
--extra_apks FDroid= \
|
|
--extra_apks FDroidPrivilegedExtension= \
|
|
"$input" "$output"
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# pota — generate a full or incremental OTA package
|
|
# pota → full OTA from signed-target_files.zip
|
|
# pota -i prev-signed.zip → incremental OTA against a previous build
|
|
# pota signed.zip out.zip → explicit input/output
|
|
# pota -i prev.zip new.zip out.zip
|
|
# pota -c <certs-dir> ... → explicit certificate directory
|
|
#
|
|
# The release-key directory comes from the -c flag or the PAWLET_CERTS_DIR
|
|
# environment variable — there is no default path.
|
|
# ---------------------------------------------------------------------------
|
|
function pota()
|
|
{
|
|
local T=$(gettop)
|
|
local certs="${PAWLET_CERTS_DIR}"
|
|
local incremental_flag=""
|
|
local input="signed-target_files.zip"
|
|
local output="pawlet-ota.zip"
|
|
local input_set=""
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-c) certs=$2; shift 2 ;;
|
|
-i) incremental_flag="-i $2"; shift 2 ;;
|
|
*)
|
|
if [ -z "$input_set" ]; then
|
|
input=$1; input_set=1
|
|
else
|
|
output=$1
|
|
fi
|
|
shift ;;
|
|
esac
|
|
done
|
|
|
|
if [ -z "$certs" ] || [ ! -d "$certs" ]; then
|
|
echo "pota: no certs dir${certs:+ at '$certs'} — pass -c <dir> or set PAWLET_CERTS_DIR." >&2
|
|
return 1
|
|
fi
|
|
|
|
echo "pota: building OTA $input → $output${incremental_flag:+ (incremental)} (keys: $certs)"
|
|
"${T}/build/make/tools/releasetools/ota_from_target_files" \
|
|
-k "${certs}/releasekey" \
|
|
$incremental_flag \
|
|
"$input" "$output"
|
|
|
|
echo "pota: done → $output"
|
|
}
|
|
|
|
echo "PawletOS build helpers loaded."
|