forked from Mirror/pmbootstrap
WIP: 2024-06-05: args hacking and more (MR 2252)
Continue removing args and do some other optimisations. Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
This commit is contained in:
parent
5bb2390d98
commit
de4c912692
52 changed files with 498 additions and 464 deletions
|
@ -54,7 +54,7 @@ def properties(pkgname):
|
||||||
raise ValueError("No generator available for " + pkgname + "!")
|
raise ValueError("No generator available for " + pkgname + "!")
|
||||||
|
|
||||||
|
|
||||||
def generate(args: PmbArgs, pkgname, fork_alpine=False):
|
def generate(pkgname, fork_alpine=False):
|
||||||
if fork_alpine:
|
if fork_alpine:
|
||||||
prefix, folder, options = (pkgname, "temp",
|
prefix, folder, options = (pkgname, "temp",
|
||||||
{"confirm_overwrite": True})
|
{"confirm_overwrite": True})
|
||||||
|
@ -83,7 +83,7 @@ def generate(args: PmbArgs, pkgname, fork_alpine=False):
|
||||||
else:
|
else:
|
||||||
# Run pmb.aportgen.PREFIX.generate()
|
# Run pmb.aportgen.PREFIX.generate()
|
||||||
# FIXME: this is really bad and hacky let's not do this please
|
# FIXME: this is really bad and hacky let's not do this please
|
||||||
getattr(pmb.aportgen, prefix.replace("-", "_")).generate(args, pkgname)
|
getattr(pmb.aportgen, prefix.replace("-", "_")).generate(pkgname)
|
||||||
|
|
||||||
# Move to the aports folder
|
# Move to the aports folder
|
||||||
if os.path.exists(path_target):
|
if os.path.exists(path_target):
|
||||||
|
|
|
@ -11,7 +11,7 @@ import pmb.parse.apkindex
|
||||||
from pmb.core import Chroot, get_context
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def generate(args: PmbArgs, pkgname):
|
def generate(pkgname):
|
||||||
arch = pkgname.split("-")[2]
|
arch = pkgname.split("-")[2]
|
||||||
context = get_context()
|
context = get_context()
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ def ask_for_flash_method():
|
||||||
" pmb/config/__init__.py.")
|
" pmb/config/__init__.py.")
|
||||||
|
|
||||||
|
|
||||||
def ask_for_bootimg(args: PmbArgs):
|
def ask_for_bootimg():
|
||||||
logging.info("You can analyze a known working boot.img file to"
|
logging.info("You can analyze a known working boot.img file to"
|
||||||
" automatically fill out the flasher information for your"
|
" automatically fill out the flasher information for your"
|
||||||
" deviceinfo file. Either specify the path to an image or"
|
" deviceinfo file. Either specify the path to an image or"
|
||||||
|
@ -114,7 +114,7 @@ def ask_for_bootimg(args: PmbArgs):
|
||||||
if not path:
|
if not path:
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
return pmb.parse.bootimg(args, path)
|
return pmb.parse.bootimg(path)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.fatal("ERROR: " + str(e) + ". Please try again.")
|
logging.fatal("ERROR: " + str(e) + ". Please try again.")
|
||||||
|
|
||||||
|
@ -319,7 +319,7 @@ def generate_apkbuild(pkgname, name, arch, flash_method):
|
||||||
handle.write(line[8:].replace(" " * 4, "\t") + "\n")
|
handle.write(line[8:].replace(" " * 4, "\t") + "\n")
|
||||||
|
|
||||||
|
|
||||||
def generate(args: PmbArgs, pkgname):
|
def generate(pkgname):
|
||||||
arch = ask_for_architecture()
|
arch = ask_for_architecture()
|
||||||
manufacturer = ask_for_manufacturer()
|
manufacturer = ask_for_manufacturer()
|
||||||
name = ask_for_name(manufacturer)
|
name = ask_for_name(manufacturer)
|
||||||
|
@ -330,7 +330,7 @@ def generate(args: PmbArgs, pkgname):
|
||||||
flash_method = ask_for_flash_method()
|
flash_method = ask_for_flash_method()
|
||||||
bootimg = None
|
bootimg = None
|
||||||
if flash_method in ["fastboot", "heimdall-bootimg"]:
|
if flash_method in ["fastboot", "heimdall-bootimg"]:
|
||||||
bootimg = ask_for_bootimg(args)
|
bootimg = ask_for_bootimg()
|
||||||
|
|
||||||
generate_deviceinfo(pkgname, name, manufacturer, year, arch,
|
generate_deviceinfo(pkgname, name, manufacturer, year, arch,
|
||||||
chassis, has_keyboard, has_external_storage,
|
chassis, has_keyboard, has_external_storage,
|
||||||
|
|
|
@ -2,18 +2,17 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
import pmb.aportgen.core
|
import pmb.aportgen.core
|
||||||
from pmb.core import get_context
|
from pmb.core import get_context
|
||||||
from pmb.types import PmbArgs
|
|
||||||
import pmb.helpers.git
|
import pmb.helpers.git
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
|
|
||||||
|
|
||||||
def generate(args: PmbArgs, pkgname):
|
def generate(pkgname):
|
||||||
# Copy original aport
|
# Copy original aport
|
||||||
prefix = pkgname.split("-")[0]
|
prefix = pkgname.split("-")[0]
|
||||||
arch = pkgname.split("-")[1]
|
arch = pkgname.split("-")[1]
|
||||||
context = get_context()
|
context = get_context()
|
||||||
if prefix == "gcc":
|
if prefix == "gcc":
|
||||||
upstream = pmb.aportgen.core.get_upstream_aport(args, "gcc", arch)
|
upstream = pmb.aportgen.core.get_upstream_aport("gcc", arch)
|
||||||
based_on = "main/gcc (from Alpine)"
|
based_on = "main/gcc (from Alpine)"
|
||||||
elif prefix == "gcc4":
|
elif prefix == "gcc4":
|
||||||
upstream = f"{context.config.aports}/main/gcc4"
|
upstream = f"{context.config.aports}/main/gcc4"
|
||||||
|
|
|
@ -11,7 +11,7 @@ import pmb.parse.apkindex
|
||||||
from pmb.core import Chroot, get_context
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def generate(args: PmbArgs, pkgname):
|
def generate(pkgname):
|
||||||
arch = "x86"
|
arch = "x86"
|
||||||
if pkgname != "grub-efi-x86":
|
if pkgname != "grub-efi-x86":
|
||||||
raise RuntimeError("only grub-efi-x86 is available")
|
raise RuntimeError("only grub-efi-x86 is available")
|
||||||
|
|
|
@ -8,7 +8,7 @@ import pmb.parse.apkindex
|
||||||
import pmb.parse.arch
|
import pmb.parse.arch
|
||||||
|
|
||||||
|
|
||||||
def generate_apkbuild(args: PmbArgs, pkgname, deviceinfo, patches):
|
def generate_apkbuild(pkgname, deviceinfo, patches):
|
||||||
device = "-".join(pkgname.split("-")[1:])
|
device = "-".join(pkgname.split("-")[1:])
|
||||||
carch = pmb.parse.arch.alpine_to_kernel(deviceinfo["arch"])
|
carch = pmb.parse.arch.alpine_to_kernel(deviceinfo["arch"])
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ def generate_apkbuild(args: PmbArgs, pkgname, deviceinfo, patches):
|
||||||
hndl.write(line[8:].replace(" " * 4, "\t") + "\n")
|
hndl.write(line[8:].replace(" " * 4, "\t") + "\n")
|
||||||
|
|
||||||
|
|
||||||
def generate(args: PmbArgs, pkgname):
|
def generate(pkgname):
|
||||||
device = "-".join(pkgname.split("-")[1:])
|
device = "-".join(pkgname.split("-")[1:])
|
||||||
deviceinfo = pmb.parse.deviceinfo(device)
|
deviceinfo = pmb.parse.deviceinfo(device)
|
||||||
work = get_context().config.work
|
work = get_context().config.work
|
||||||
|
@ -129,4 +129,4 @@ def generate(args: PmbArgs, pkgname):
|
||||||
"../../.shared-patches/linux/" + patch,
|
"../../.shared-patches/linux/" + patch,
|
||||||
(work / "aportgen" / patch)])
|
(work / "aportgen" / patch)])
|
||||||
|
|
||||||
generate_apkbuild(args, pkgname, deviceinfo, patches)
|
generate_apkbuild(pkgname, deviceinfo, patches)
|
||||||
|
|
|
@ -5,13 +5,12 @@ import pmb.aportgen.core
|
||||||
import pmb.build
|
import pmb.build
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
import pmb.chroot.apk_static
|
import pmb.chroot.apk_static
|
||||||
from pmb.types import PmbArgs
|
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.parse.apkindex
|
import pmb.parse.apkindex
|
||||||
from pmb.core import Chroot, get_context
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def generate(args: PmbArgs, pkgname):
|
def generate(pkgname):
|
||||||
arch = pkgname.split("-")[1]
|
arch = pkgname.split("-")[1]
|
||||||
|
|
||||||
# Parse musl version from APKINDEX
|
# Parse musl version from APKINDEX
|
||||||
|
|
|
@ -56,13 +56,14 @@ def arch(args: PmbArgs, pkgname: str):
|
||||||
|
|
||||||
apkbuild = pmb.parse.apkbuild(aport)
|
apkbuild = pmb.parse.apkbuild(aport)
|
||||||
arches = apkbuild["arch"]
|
arches = apkbuild["arch"]
|
||||||
|
deviceinfo = pmb.parse.deviceinfo()
|
||||||
|
|
||||||
if get_context().config.build_default_device_arch:
|
if get_context().config.build_default_device_arch:
|
||||||
preferred_arch = args.deviceinfo["arch"]
|
preferred_arch = deviceinfo["arch"]
|
||||||
preferred_arch_2nd = pmb.config.arch_native
|
preferred_arch_2nd = pmb.config.arch_native
|
||||||
else:
|
else:
|
||||||
preferred_arch = pmb.config.arch_native
|
preferred_arch = pmb.config.arch_native
|
||||||
preferred_arch_2nd = args.deviceinfo["arch"]
|
preferred_arch_2nd = deviceinfo["arch"]
|
||||||
|
|
||||||
if "noarch" in arches or "all" in arches or preferred_arch in arches:
|
if "noarch" in arches or "all" in arches or preferred_arch in arches:
|
||||||
return preferred_arch
|
return preferred_arch
|
||||||
|
|
|
@ -190,7 +190,7 @@ def package_kernel(args: PmbArgs):
|
||||||
modify_apkbuild(pkgname, aport)
|
modify_apkbuild(pkgname, aport)
|
||||||
apkbuild_path = context.config.work / "aportgen/APKBUILD"
|
apkbuild_path = context.config.work / "aportgen/APKBUILD"
|
||||||
|
|
||||||
arch = args.deviceinfo["arch"]
|
arch = pmb.parse.deviceinfo()["arch"]
|
||||||
apkbuild = pmb.parse.apkbuild(apkbuild_path, check_pkgname=False)
|
apkbuild = pmb.parse.apkbuild(apkbuild_path, check_pkgname=False)
|
||||||
if apkbuild["_outdir"]:
|
if apkbuild["_outdir"]:
|
||||||
kbuild_out = apkbuild["_outdir"]
|
kbuild_out = apkbuild["_outdir"]
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
import os
|
import os
|
||||||
|
from pmb.core.context import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
@ -84,8 +85,8 @@ def get_outputdir(args: PmbArgs, pkgname: str, apkbuild: Dict[str, Any]) -> Path
|
||||||
" template with: pmbootstrap aportgen " + pkgname)
|
" template with: pmbootstrap aportgen " + pkgname)
|
||||||
|
|
||||||
|
|
||||||
def extract_and_patch_sources(args: PmbArgs, pkgname: str, arch):
|
def extract_and_patch_sources(pkgname: str, arch):
|
||||||
pmb.build.copy_to_buildpath(args, pkgname)
|
pmb.build.copy_to_buildpath(pkgname)
|
||||||
logging.info("(native) extract kernel source")
|
logging.info("(native) extract kernel source")
|
||||||
pmb.chroot.user(["abuild", "unpack"], working_dir=Path("/home/pmos/build"))
|
pmb.chroot.user(["abuild", "unpack"], working_dir=Path("/home/pmos/build"))
|
||||||
logging.info("(native) apply patches")
|
logging.info("(native) apply patches")
|
||||||
|
@ -102,14 +103,14 @@ def menuconfig(args: PmbArgs, pkgname: str, use_oldconfig):
|
||||||
aport = pmb.helpers.pmaports.find(pkgname)
|
aport = pmb.helpers.pmaports.find(pkgname)
|
||||||
apkbuild = pmb.parse.apkbuild(aport / "APKBUILD")
|
apkbuild = pmb.parse.apkbuild(aport / "APKBUILD")
|
||||||
arch = args.arch or get_arch(apkbuild)
|
arch = args.arch or get_arch(apkbuild)
|
||||||
suffix = pmb.build.autodetect.chroot(apkbuild, arch)
|
chroot = pmb.build.autodetect.chroot(apkbuild, arch)
|
||||||
cross = pmb.build.autodetect.crosscompile(args, apkbuild, arch, suffix)
|
cross = pmb.build.autodetect.crosscompile(apkbuild, arch, chroot)
|
||||||
hostspec = pmb.parse.arch.alpine_to_hostspec(arch)
|
hostspec = pmb.parse.arch.alpine_to_hostspec(arch)
|
||||||
|
|
||||||
# Set up build tools and makedepends
|
# Set up build tools and makedepends
|
||||||
pmb.build.init(args, suffix)
|
pmb.build.init(chroot)
|
||||||
if cross:
|
if cross:
|
||||||
pmb.build.init_compiler(args, [], cross, arch)
|
pmb.build.init_compiler(get_context(), [], cross, arch)
|
||||||
|
|
||||||
depends = apkbuild["makedepends"]
|
depends = apkbuild["makedepends"]
|
||||||
copy_xauth = False
|
copy_xauth = False
|
||||||
|
@ -128,13 +129,13 @@ def menuconfig(args: PmbArgs, pkgname: str, use_oldconfig):
|
||||||
else:
|
else:
|
||||||
depends += ["ncurses-dev"]
|
depends += ["ncurses-dev"]
|
||||||
|
|
||||||
pmb.chroot.apk.install(depends)
|
pmb.chroot.apk.install(depends, Chroot.native())
|
||||||
|
|
||||||
# Copy host's .xauthority into native
|
# Copy host's .xauthority into native
|
||||||
if copy_xauth:
|
if copy_xauth:
|
||||||
pmb.chroot.other.copy_xauthority(args)
|
pmb.chroot.other.copy_xauthority(args)
|
||||||
|
|
||||||
extract_and_patch_sources(args, pkgname, arch)
|
extract_and_patch_sources(pkgname, arch)
|
||||||
|
|
||||||
# Check for background color variable
|
# Check for background color variable
|
||||||
color = os.environ.get("MENUCONFIG_COLOR")
|
color = os.environ.get("MENUCONFIG_COLOR")
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import os
|
import os
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import pmb.chroot.run
|
import pmb.chroot
|
||||||
from pmb.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.cli
|
import pmb.helpers.cli
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
|
|
|
@ -9,6 +9,7 @@ from typing import List
|
||||||
|
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
from pmb.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
|
import pmb.build
|
||||||
import pmb.helpers.file
|
import pmb.helpers.file
|
||||||
import pmb.helpers.git
|
import pmb.helpers.git
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
|
@ -99,7 +100,7 @@ def index_repo(args: PmbArgs, arch=None):
|
||||||
|
|
||||||
:param arch: when not defined, re-index all repos
|
:param arch: when not defined, re-index all repos
|
||||||
"""
|
"""
|
||||||
pmb.build.init(args)
|
pmb.build.init()
|
||||||
|
|
||||||
channel = pmb.config.pmaports.read_config()["channel"]
|
channel = pmb.config.pmaports.read_config()["channel"]
|
||||||
pkgdir = (get_context().config.work / "packages" / channel)
|
pkgdir = (get_context().config.work / "packages" / channel)
|
||||||
|
|
|
@ -11,10 +11,10 @@ import pmb.helpers.cli
|
||||||
from pmb.core import Chroot, get_context
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def build(args: PmbArgs, flavor, chroot: Chroot):
|
def build(flavor, chroot: Chroot):
|
||||||
# Update mkinitfs and hooks
|
# Update mkinitfs and hooks
|
||||||
pmb.chroot.apk.install(["postmarketos-mkinitfs"], chroot)
|
pmb.chroot.apk.install(["postmarketos-mkinitfs"], chroot)
|
||||||
pmb.chroot.initfs_hooks.update(args, chroot)
|
pmb.chroot.initfs_hooks.update(chroot)
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config()
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
|
|
||||||
# Call mkinitfs
|
# Call mkinitfs
|
||||||
|
@ -30,7 +30,7 @@ def build(args: PmbArgs, flavor, chroot: Chroot):
|
||||||
chroot)
|
chroot)
|
||||||
|
|
||||||
|
|
||||||
def extract(args: PmbArgs, flavor, chroot: Chroot, extra=False):
|
def extract(flavor, chroot: Chroot, extra=False):
|
||||||
"""
|
"""
|
||||||
Extract the initramfs to /tmp/initfs-extracted or the initramfs-extra to
|
Extract the initramfs to /tmp/initfs-extracted or the initramfs-extra to
|
||||||
/tmp/initfs-extra-extracted and return the outside extraction path.
|
/tmp/initfs-extra-extracted and return the outside extraction path.
|
||||||
|
@ -77,11 +77,11 @@ def extract(args: PmbArgs, flavor, chroot: Chroot, extra=False):
|
||||||
return outside
|
return outside
|
||||||
|
|
||||||
|
|
||||||
def ls(args: PmbArgs, flavor, suffix, extra=False):
|
def ls( flavor, suffix, extra=False):
|
||||||
tmp = "/tmp/initfs-extracted"
|
tmp = "/tmp/initfs-extracted"
|
||||||
if extra:
|
if extra:
|
||||||
tmp = "/tmp/initfs-extra-extracted"
|
tmp = "/tmp/initfs-extra-extracted"
|
||||||
extract(args, flavor, suffix, extra)
|
extract(flavor, suffix, extra)
|
||||||
pmb.chroot.root(["ls", "-lahR", "."], suffix, Path(tmp), "stdout")
|
pmb.chroot.root(["ls", "-lahR", "."], suffix, Path(tmp), "stdout")
|
||||||
pmb.chroot.root(["rm", "-r", tmp], suffix)
|
pmb.chroot.root(["rm", "-r", tmp], suffix)
|
||||||
|
|
||||||
|
@ -95,17 +95,17 @@ def frontend(args: PmbArgs):
|
||||||
# Handle initfs actions
|
# Handle initfs actions
|
||||||
action = args.action_initfs
|
action = args.action_initfs
|
||||||
if action == "build":
|
if action == "build":
|
||||||
build(args, flavor, chroot)
|
build(flavor, chroot)
|
||||||
elif action == "extract":
|
elif action == "extract":
|
||||||
dir = extract(args, flavor, chroot)
|
dir = extract(flavor, chroot)
|
||||||
logging.info(f"Successfully extracted initramfs to: {dir}")
|
logging.info(f"Successfully extracted initramfs to: {dir}")
|
||||||
dir_extra = extract(args, flavor, chroot, True)
|
dir_extra = extract(flavor, chroot, True)
|
||||||
logging.info(f"Successfully extracted initramfs-extra to: {dir_extra}")
|
logging.info(f"Successfully extracted initramfs-extra to: {dir_extra}")
|
||||||
elif action == "ls":
|
elif action == "ls":
|
||||||
logging.info("*** initramfs ***")
|
logging.info("*** initramfs ***")
|
||||||
ls(args, flavor, chroot)
|
ls(flavor, chroot)
|
||||||
logging.info("*** initramfs-extra ***")
|
logging.info("*** initramfs-extra ***")
|
||||||
ls(args, flavor, chroot, True)
|
ls(flavor, chroot, True)
|
||||||
|
|
||||||
# Handle hook actions
|
# Handle hook actions
|
||||||
elif action == "hook_ls":
|
elif action == "hook_ls":
|
||||||
|
@ -117,7 +117,7 @@ def frontend(args: PmbArgs):
|
||||||
pmb.chroot.initfs_hooks.delete(args.hook, chroot)
|
pmb.chroot.initfs_hooks.delete(args.hook, chroot)
|
||||||
|
|
||||||
# Rebuild the initfs after adding/removing a hook
|
# Rebuild the initfs after adding/removing a hook
|
||||||
build(args, flavor, chroot)
|
build(flavor, chroot)
|
||||||
|
|
||||||
if action in ["ls", "extract"]:
|
if action in ["ls", "extract"]:
|
||||||
link = "https://wiki.postmarketos.org/wiki/Initramfs_development"
|
link = "https://wiki.postmarketos.org/wiki/Initramfs_development"
|
||||||
|
|
|
@ -55,7 +55,7 @@ def delete(hook, suffix: Chroot):
|
||||||
pmb.chroot.root(["apk", "del", f"{prefix}{hook}"], suffix)
|
pmb.chroot.root(["apk", "del", f"{prefix}{hook}"], suffix)
|
||||||
|
|
||||||
|
|
||||||
def update(args: PmbArgs, suffix: Chroot):
|
def update(suffix: Chroot):
|
||||||
"""
|
"""
|
||||||
Rebuild and update all hooks that are out of date
|
Rebuild and update all hooks that are out of date
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -5,6 +5,7 @@ import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
import pmb.config
|
import pmb.config
|
||||||
|
import pmb.chroot.apk
|
||||||
from pmb.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
|
@ -98,7 +99,7 @@ def mount(chroot: Chroot):
|
||||||
pmb.helpers.mount.bind(source, target_outer)
|
pmb.helpers.mount.bind(source, target_outer)
|
||||||
|
|
||||||
|
|
||||||
def mount_native_into_foreign(args: PmbArgs, chroot: Chroot):
|
def mount_native_into_foreign(chroot: Chroot):
|
||||||
source = Chroot.native().path
|
source = Chroot.native().path
|
||||||
target = chroot / "native"
|
target = chroot / "native"
|
||||||
pmb.helpers.mount.bind(source, target)
|
pmb.helpers.mount.bind(source, target)
|
||||||
|
|
|
@ -115,7 +115,7 @@ def zap_pkgs_local_mismatch(args: PmbArgs, confirm=True, dry=False):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Aport path
|
# Aport path
|
||||||
aport_path = pmb.helpers.pmaports.find_optional(args, origin)
|
aport_path = pmb.helpers.pmaports.find_optional(origin)
|
||||||
if not aport_path:
|
if not aport_path:
|
||||||
logging.info(f"% rm {apk_path_short}"
|
logging.info(f"% rm {apk_path_short}"
|
||||||
f" ({origin} aport not found)")
|
f" ({origin} aport not found)")
|
||||||
|
|
|
@ -114,7 +114,7 @@ def ask_which_scripts_to_run(scripts_available):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def copy_git_repo_to_chroot(args: PmbArgs, topdir):
|
def copy_git_repo_to_chroot(topdir):
|
||||||
""" Create a tarball of the git repo (including unstaged changes and new
|
""" Create a tarball of the git repo (including unstaged changes and new
|
||||||
files) and extract it in chroot_native.
|
files) and extract it in chroot_native.
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ def copy_git_repo_to_chroot(args: PmbArgs, topdir):
|
||||||
pmb.helpers.git.get_topdir()
|
pmb.helpers.git.get_topdir()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
pmb.chroot.init(args)
|
pmb.chroot.init()
|
||||||
tarball_path = Chroot.native() / "tmp/git.tar.gz"
|
tarball_path = Chroot.native() / "tmp/git.tar.gz"
|
||||||
files = pmb.helpers.git.get_files(topdir)
|
files = pmb.helpers.git.get_files(topdir)
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ def copy_git_repo_to_chroot(args: PmbArgs, topdir):
|
||||||
working_dir=ci_dir)
|
working_dir=ci_dir)
|
||||||
|
|
||||||
|
|
||||||
def run_scripts(args: PmbArgs, topdir, scripts):
|
def run_scripts(topdir, scripts):
|
||||||
""" Run one of the given scripts after another, either natively or in a
|
""" Run one of the given scripts after another, either natively or in a
|
||||||
chroot. Display a progress message and stop on error (without printing
|
chroot. Display a progress message and stop on error (without printing
|
||||||
a python stack trace).
|
a python stack trace).
|
||||||
|
@ -174,7 +174,7 @@ def run_scripts(args: PmbArgs, topdir, scripts):
|
||||||
else:
|
else:
|
||||||
# Run inside pmbootstrap chroot
|
# Run inside pmbootstrap chroot
|
||||||
if not repo_copied:
|
if not repo_copied:
|
||||||
copy_git_repo_to_chroot(args, topdir)
|
copy_git_repo_to_chroot(topdir)
|
||||||
repo_copied = True
|
repo_copied = True
|
||||||
|
|
||||||
env = {"TESTUSER": "pmos"}
|
env = {"TESTUSER": "pmos"}
|
||||||
|
|
|
@ -8,7 +8,6 @@ from pmb import commands
|
||||||
from pmb.types import PathString
|
from pmb.types import PathString
|
||||||
from pmb.helpers import run
|
from pmb.helpers import run
|
||||||
from pmb.core import get_context
|
from pmb.core import get_context
|
||||||
from pmb import config
|
|
||||||
|
|
||||||
class Log(commands.Command):
|
class Log(commands.Command):
|
||||||
clear_log: bool
|
clear_log: bool
|
||||||
|
@ -20,7 +19,7 @@ class Log(commands.Command):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
context = get_context()
|
context = get_context()
|
||||||
log_testsuite = config.work / "log_testsuite.txt"
|
log_testsuite = context.config.work / "log_testsuite.txt"
|
||||||
|
|
||||||
if self.clear_log:
|
if self.clear_log:
|
||||||
run.user(["truncate", "-s", "0", context.log])
|
run.user(["truncate", "-s", "0", context.log])
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
from pmb.core import get_context
|
from pmb.core import get_context
|
||||||
from pmb.core.chroot import Chroot
|
from pmb.core.chroot import Chroot
|
||||||
|
from pmb.core.context import Context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import glob
|
import glob
|
||||||
import json
|
import json
|
||||||
|
@ -38,13 +39,13 @@ def require_programs():
|
||||||
f" {', '.join(missing)}")
|
f" {', '.join(missing)}")
|
||||||
|
|
||||||
|
|
||||||
def ask_for_username(args: PmbArgs):
|
def ask_for_username(args: PmbArgs, default_user: str):
|
||||||
"""Ask for a reasonable username for the non-root user.
|
"""Ask for a reasonable username for the non-root user.
|
||||||
|
|
||||||
:returns: the username
|
:returns: the username
|
||||||
"""
|
"""
|
||||||
while True:
|
while True:
|
||||||
ret = pmb.helpers.cli.ask("Username", None, args.user, False,
|
ret = pmb.helpers.cli.ask("Username", None, default_user, False,
|
||||||
"[a-z_][a-z0-9_-]*")
|
"[a-z_][a-z0-9_-]*")
|
||||||
if ret == "root":
|
if ret == "root":
|
||||||
logging.fatal("ERROR: don't put \"root\" here. This is about"
|
logging.fatal("ERROR: don't put \"root\" here. This is about"
|
||||||
|
@ -139,8 +140,8 @@ def ask_for_channel(args: PmbArgs):
|
||||||
" from the list above.")
|
" from the list above.")
|
||||||
|
|
||||||
|
|
||||||
def ask_for_ui(args: PmbArgs, info):
|
def ask_for_ui(info):
|
||||||
ui_list = pmb.helpers.ui.list_ui(args, info["arch"])
|
ui_list = pmb.helpers.ui.list_ui(info["arch"])
|
||||||
hidden_ui_count = 0
|
hidden_ui_count = 0
|
||||||
device_is_accelerated = info.get("gpu_accelerated") == "true"
|
device_is_accelerated = info.get("gpu_accelerated") == "true"
|
||||||
if not device_is_accelerated:
|
if not device_is_accelerated:
|
||||||
|
@ -154,7 +155,7 @@ def ask_for_ui(args: PmbArgs, info):
|
||||||
hidden_ui_count += 1
|
hidden_ui_count += 1
|
||||||
|
|
||||||
# Get default
|
# Get default
|
||||||
default: Any = args.ui
|
default: Any = get_context().config.ui
|
||||||
if default not in dict(ui_list).keys():
|
if default not in dict(ui_list).keys():
|
||||||
default = pmb.config.defaults["ui"]
|
default = pmb.config.defaults["ui"]
|
||||||
|
|
||||||
|
@ -176,7 +177,7 @@ def ask_for_ui(args: PmbArgs, info):
|
||||||
" one from the list above.")
|
" one from the list above.")
|
||||||
|
|
||||||
|
|
||||||
def ask_for_ui_extras(args: PmbArgs, ui):
|
def ask_for_ui_extras(config: Config, ui):
|
||||||
apkbuild = pmb.helpers.pmaports.get(f"postmarketos-ui-{ui}",
|
apkbuild = pmb.helpers.pmaports.get(f"postmarketos-ui-{ui}",
|
||||||
subpackages=False, must_exist=False)
|
subpackages=False, must_exist=False)
|
||||||
if not apkbuild:
|
if not apkbuild:
|
||||||
|
@ -190,17 +191,17 @@ def ask_for_ui_extras(args: PmbArgs, ui):
|
||||||
f" {extra['pkgdesc']}")
|
f" {extra['pkgdesc']}")
|
||||||
|
|
||||||
return pmb.helpers.cli.confirm("Enable this package?",
|
return pmb.helpers.cli.confirm("Enable this package?",
|
||||||
default=args.ui_extras)
|
default=config.ui_extras)
|
||||||
|
|
||||||
|
|
||||||
def ask_for_systemd(args: PmbArgs, ui):
|
def ask_for_systemd(config: Config, ui):
|
||||||
if "systemd" not in pmb.config.pmaports.read_config_repos():
|
if "systemd" not in pmb.config.pmaports.read_config_repos():
|
||||||
return args.systemd
|
return config.systemd
|
||||||
|
|
||||||
if pmb.helpers.ui.check_option(ui, "pmb:systemd-never"):
|
if pmb.helpers.ui.check_option(ui, "pmb:systemd-never"):
|
||||||
logging.info("Based on your UI selection, OpenRC will be used as init"
|
logging.info("Based on your UI selection, OpenRC will be used as init"
|
||||||
" system. This UI does not support systemd.")
|
" system. This UI does not support systemd.")
|
||||||
return args.systemd
|
return config.systemd
|
||||||
|
|
||||||
default_is_systemd = pmb.helpers.ui.check_option(ui, "pmb:systemd")
|
default_is_systemd = pmb.helpers.ui.check_option(ui, "pmb:systemd")
|
||||||
not_str = " " if default_is_systemd else " not "
|
not_str = " " if default_is_systemd else " not "
|
||||||
|
@ -210,7 +211,7 @@ def ask_for_systemd(args: PmbArgs, ui):
|
||||||
choices = pmb.config.allowed_values["systemd"]
|
choices = pmb.config.allowed_values["systemd"]
|
||||||
answer = pmb.helpers.cli.ask("Install systemd?",
|
answer = pmb.helpers.cli.ask("Install systemd?",
|
||||||
choices,
|
choices,
|
||||||
args.systemd,
|
config.systemd,
|
||||||
validation_regex=f"^({'|'.join(choices)})$",
|
validation_regex=f"^({'|'.join(choices)})$",
|
||||||
complete=choices)
|
complete=choices)
|
||||||
return answer
|
return answer
|
||||||
|
@ -314,7 +315,7 @@ def ask_for_provider_select(apkbuild, providers_cfg):
|
||||||
" one from the list above.")
|
" one from the list above.")
|
||||||
|
|
||||||
|
|
||||||
def ask_for_provider_select_pkg(args: PmbArgs, pkgname, providers_cfg):
|
def ask_for_provider_select_pkg(pkgname, providers_cfg):
|
||||||
"""Look up the APKBUILD for the specified pkgname and ask for selectable
|
"""Look up the APKBUILD for the specified pkgname and ask for selectable
|
||||||
providers that are specified using "_pmb_select".
|
providers that are specified using "_pmb_select".
|
||||||
|
|
||||||
|
@ -327,10 +328,10 @@ def ask_for_provider_select_pkg(args: PmbArgs, pkgname, providers_cfg):
|
||||||
if not apkbuild:
|
if not apkbuild:
|
||||||
return
|
return
|
||||||
|
|
||||||
ask_for_provider_select(args, apkbuild, providers_cfg)
|
ask_for_provider_select(apkbuild, providers_cfg)
|
||||||
|
|
||||||
|
|
||||||
def ask_for_device_kernel(args: PmbArgs, device: str):
|
def ask_for_device_kernel(config: Config, device: str):
|
||||||
"""Ask for the kernel that should be used with the device.
|
"""Ask for the kernel that should be used with the device.
|
||||||
|
|
||||||
:param device: code name, e.g. "lg-mako"
|
:param device: code name, e.g. "lg-mako"
|
||||||
|
@ -343,10 +344,10 @@ def ask_for_device_kernel(args: PmbArgs, device: str):
|
||||||
# Get kernels
|
# Get kernels
|
||||||
kernels = pmb.parse._apkbuild.kernels(device)
|
kernels = pmb.parse._apkbuild.kernels(device)
|
||||||
if not kernels:
|
if not kernels:
|
||||||
return args.kernel
|
return config.kernel
|
||||||
|
|
||||||
# Get default
|
# Get default
|
||||||
default = args.kernel
|
default = config.kernel
|
||||||
if default not in kernels:
|
if default not in kernels:
|
||||||
default = list(kernels.keys())[0]
|
default = list(kernels.keys())[0]
|
||||||
|
|
||||||
|
@ -374,7 +375,7 @@ def ask_for_device_kernel(args: PmbArgs, device: str):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def ask_for_device(config: Config):
|
def ask_for_device(context: Context):
|
||||||
"""
|
"""
|
||||||
Prompt for the device vendor, model, and kernel.
|
Prompt for the device vendor, model, and kernel.
|
||||||
|
|
||||||
|
@ -383,16 +384,16 @@ def ask_for_device(config: Config):
|
||||||
* device_exists: bool indicating if device port exists in repo
|
* device_exists: bool indicating if device port exists in repo
|
||||||
* kernel: type of kernel (downstream, etc)
|
* kernel: type of kernel (downstream, etc)
|
||||||
"""
|
"""
|
||||||
vendors = sorted(pmb.helpers.devices.list_vendors(get_context().config.aports))
|
vendors = sorted(pmb.helpers.devices.list_vendors(context.config.aports))
|
||||||
logging.info("Choose your target device vendor (either an "
|
logging.info("Choose your target device vendor (either an "
|
||||||
"existing one, or a new one for porting).")
|
"existing one, or a new one for porting).")
|
||||||
logging.info(f"Available vendors ({len(vendors)}): {', '.join(vendors)}")
|
logging.info(f"Available vendors ({len(vendors)}): {', '.join(vendors)}")
|
||||||
|
|
||||||
current_vendor = None
|
current_vendor = None
|
||||||
current_codename = None
|
current_codename = None
|
||||||
if config.device:
|
if context.config.device:
|
||||||
current_vendor = config.device.split("-", 1)[0]
|
current_vendor = context.config.device.split("-", 1)[0]
|
||||||
current_codename = config.device.split("-", 1)[1]
|
current_codename = context.config.device.split("-", 1)[1]
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
vendor = pmb.helpers.cli.ask("Vendor", None, current_vendor,
|
vendor = pmb.helpers.cli.ask("Vendor", None, current_vendor,
|
||||||
|
@ -409,7 +410,7 @@ def ask_for_device(config: Config):
|
||||||
else:
|
else:
|
||||||
# Archived devices can be selected, but are not displayed
|
# Archived devices can be selected, but are not displayed
|
||||||
devices = sorted(pmb.helpers.devices.list_codenames(
|
devices = sorted(pmb.helpers.devices.list_codenames(
|
||||||
get_context().config.aports, vendor, archived=False))
|
context.config.aports, vendor, archived=False))
|
||||||
# Remove "vendor-" prefixes from device list
|
# Remove "vendor-" prefixes from device list
|
||||||
codenames = [x.split('-', 1)[1] for x in devices]
|
codenames = [x.split('-', 1)[1] for x in devices]
|
||||||
logging.info(f"Available codenames ({len(codenames)}): " +
|
logging.info(f"Available codenames ({len(codenames)}): " +
|
||||||
|
@ -424,7 +425,7 @@ def ask_for_device(config: Config):
|
||||||
device = f"{vendor}-{codename}"
|
device = f"{vendor}-{codename}"
|
||||||
device_path = pmb.helpers.devices.find_path(device, 'deviceinfo')
|
device_path = pmb.helpers.devices.find_path(device, 'deviceinfo')
|
||||||
if device_path is None:
|
if device_path is None:
|
||||||
if device == args.devicesdhbfvhubsud:
|
if device == context.device:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"This device does not exist anymore, check"
|
"This device does not exist anymore, check"
|
||||||
" <https://postmarketos.org/renamed>"
|
" <https://postmarketos.org/renamed>"
|
||||||
|
@ -440,14 +441,14 @@ def ask_for_device(config: Config):
|
||||||
pmb.aportgen.generate(f"device-{device}")
|
pmb.aportgen.generate(f"device-{device}")
|
||||||
pmb.aportgen.generate(f"linux-{device}")
|
pmb.aportgen.generate(f"linux-{device}")
|
||||||
elif any("archived" == x for x in device_path.parts):
|
elif any("archived" == x for x in device_path.parts):
|
||||||
apkbuild = f"{device_path[:-len('deviceinfo')]}APKBUILD"
|
apkbuild = device_path.parent / "APKBUILD"
|
||||||
archived = pmb.parse._apkbuild.archived(apkbuild)
|
archived = pmb.parse._apkbuild.archived(apkbuild)
|
||||||
logging.info(f"WARNING: {device} is archived: {archived}")
|
logging.info(f"WARNING: {device} is archived: {archived}")
|
||||||
if not pmb.helpers.cli.confirm(args):
|
if not pmb.helpers.cli.confirm():
|
||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
|
|
||||||
kernel = ask_for_device_kernel(args, device)
|
kernel = ask_for_device_kernel(context.config, device)
|
||||||
return (device, device_path is not None, kernel)
|
return (device, device_path is not None, kernel)
|
||||||
|
|
||||||
|
|
||||||
|
@ -675,7 +676,7 @@ def frontend(args: PmbArgs):
|
||||||
pmb.config.pmaports.install_githooks()
|
pmb.config.pmaports.install_githooks()
|
||||||
|
|
||||||
# Device
|
# Device
|
||||||
device, device_exists, kernel = ask_for_device(config)
|
device, device_exists, kernel = ask_for_device(get_context())
|
||||||
config.device = device
|
config.device = device
|
||||||
config.kernel = kernel
|
config.kernel = kernel
|
||||||
|
|
||||||
|
@ -689,19 +690,19 @@ def frontend(args: PmbArgs):
|
||||||
if device_exists:
|
if device_exists:
|
||||||
config.keymap = ask_for_keymaps(args, info)
|
config.keymap = ask_for_keymaps(args, info)
|
||||||
|
|
||||||
config.user = ask_for_username(args)
|
config.user = ask_for_username(args, config.user)
|
||||||
ask_for_provider_select_pkg(args, "postmarketos-base", config.providers)
|
ask_for_provider_select_pkg("postmarketos-base", config.providers)
|
||||||
ask_for_provider_select_pkg(args, "postmarketos-base-ui", config.providers)
|
ask_for_provider_select_pkg("postmarketos-base-ui", config.providers)
|
||||||
|
|
||||||
# UI and various build options
|
# UI and various build options
|
||||||
ui = ask_for_ui(args, info)
|
ui = ask_for_ui(info)
|
||||||
config.ui = ui
|
config.ui = ui
|
||||||
config.ui_extras = ask_for_ui_extras(args, ui)
|
config.ui_extras = ask_for_ui_extras(config, ui)
|
||||||
|
|
||||||
# systemd
|
# systemd
|
||||||
config.systemd = ask_for_systemd(args, ui)
|
config.systemd = ask_for_systemd(config, ui)
|
||||||
|
|
||||||
ask_for_provider_select_pkg(args, f"postmarketos-ui-{ui}",
|
ask_for_provider_select_pkg(f"postmarketos-ui-{ui}",
|
||||||
config.providers)
|
config.providers)
|
||||||
ask_for_additional_options(args, config)
|
ask_for_additional_options(args, config)
|
||||||
|
|
||||||
|
|
|
@ -13,14 +13,22 @@ class Context():
|
||||||
quiet: bool = False
|
quiet: bool = False
|
||||||
command_timeout: float = 900
|
command_timeout: float = 900
|
||||||
sudo_timer: bool = False
|
sudo_timer: bool = False
|
||||||
|
force: bool = False
|
||||||
log: Path
|
log: Path
|
||||||
# The architecture of the selected device
|
# The architecture of the selected device
|
||||||
device_arch: Optional[str] = None
|
device_arch: Optional[str] = None
|
||||||
offline: bool = False
|
|
||||||
|
|
||||||
# assume yes to prompts
|
# assume yes to prompts
|
||||||
assume_yes: bool = False
|
assume_yes: bool = False
|
||||||
|
|
||||||
|
# Operate offline
|
||||||
|
offline: bool = False
|
||||||
|
|
||||||
|
# Device we are operating on
|
||||||
|
# FIXME: should not be in global context, only
|
||||||
|
# specific actions actually depend on this
|
||||||
|
device: str = ""
|
||||||
|
|
||||||
# The pmbootstrap subcommand
|
# The pmbootstrap subcommand
|
||||||
command: str = ""
|
command: str = ""
|
||||||
|
|
||||||
|
@ -41,6 +49,7 @@ class Context():
|
||||||
|
|
||||||
__context: Context
|
__context: Context
|
||||||
|
|
||||||
|
# mypy: disable-error-code="return-value"
|
||||||
def get_context(allow_failure: bool=False) -> Context:
|
def get_context(allow_failure: bool=False) -> Context:
|
||||||
"""Get immutable global runtime context."""
|
"""Get immutable global runtime context."""
|
||||||
global __context
|
global __context
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from pmb.core.context import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
@ -9,7 +10,8 @@ import pmb.export
|
||||||
from pmb.core import Chroot, ChrootType
|
from pmb.core import Chroot, ChrootType
|
||||||
|
|
||||||
|
|
||||||
def frontend(args: PmbArgs):
|
def frontend(args: PmbArgs): # FIXME: ARGS_REFACTOR
|
||||||
|
context = get_context()
|
||||||
# Create the export folder
|
# Create the export folder
|
||||||
target = args.export_folder
|
target = args.export_folder
|
||||||
if not os.path.exists(target):
|
if not os.path.exists(target):
|
||||||
|
@ -17,18 +19,18 @@ def frontend(args: PmbArgs):
|
||||||
|
|
||||||
# Rootfs image note
|
# Rootfs image note
|
||||||
chroot = Chroot.native()
|
chroot = Chroot.native()
|
||||||
rootfs_dir = chroot / "home/pmos/rootfs" / args.devicesdhbfvhubsud
|
rootfs_dir = chroot / "home/pmos/rootfs" / context.device
|
||||||
if not rootfs_dir.glob("*.img"):
|
if not rootfs_dir.glob("*.img"):
|
||||||
logging.info("NOTE: To export the rootfs image, run 'pmbootstrap"
|
logging.info("NOTE: To export the rootfs image, run 'pmbootstrap"
|
||||||
" install' first (without the 'disk' parameter).")
|
" install' first (without the 'disk' parameter).")
|
||||||
|
|
||||||
# Rebuild the initramfs, just to make sure (see #69)
|
# Rebuild the initramfs, just to make sure (see #69)
|
||||||
flavor = pmb.helpers.frontend._parse_flavor(args, args.autoinstall)
|
flavor = pmb.helpers.frontend._parse_flavor(context.device, args.autoinstall)
|
||||||
if args.autoinstall:
|
if args.autoinstall:
|
||||||
pmb.chroot.initfs.build(args, flavor, Chroot(ChrootType.ROOTFS, args.devicesdhbfvhubsud))
|
pmb.chroot.initfs.build(flavor, Chroot(ChrootType.ROOTFS, context.device))
|
||||||
|
|
||||||
# Do the export, print all files
|
# Do the export, print all files
|
||||||
logging.info(f"Export symlinks to: {target}")
|
logging.info(f"Export symlinks to: {target}")
|
||||||
if args.odin_flashable_tar:
|
if args.odin_flashable_tar:
|
||||||
pmb.export.odin(args, flavor, target)
|
pmb.export.odin(context, flavor, target)
|
||||||
pmb.export.symlinks(args, flavor, target)
|
pmb.export.symlinks(args, flavor, target)
|
||||||
|
|
|
@ -1,25 +1,26 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
from pmb.core.context import Context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import pmb.build
|
import pmb.build
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.types import PmbArgs
|
|
||||||
import pmb.flasher
|
import pmb.flasher
|
||||||
import pmb.helpers.file
|
import pmb.helpers.file
|
||||||
from pmb.core import Chroot, ChrootType
|
from pmb.core import Chroot, ChrootType
|
||||||
|
|
||||||
|
|
||||||
def odin(args: PmbArgs, flavor, folder: Path):
|
def odin(context: Context, flavor, folder: Path):
|
||||||
"""
|
"""
|
||||||
Create Odin flashable tar file with kernel and initramfs
|
Create Odin flashable tar file with kernel and initramfs
|
||||||
for devices configured with the flasher method 'heimdall-isorec'
|
for devices configured with the flasher method 'heimdall-isorec'
|
||||||
and with boot.img for devices with 'heimdall-bootimg'
|
and with boot.img for devices with 'heimdall-bootimg'
|
||||||
"""
|
"""
|
||||||
pmb.flasher.init(args)
|
pmb.flasher.init(context.device)
|
||||||
suffix = Chroot(ChrootType.ROOTFS, args.devicesdhbfvhubsud)
|
suffix = Chroot(ChrootType.ROOTFS, context.device)
|
||||||
|
deviceinfo = pmb.parse.deviceinfo(context.device)
|
||||||
|
|
||||||
# Backwards compatibility with old mkinitfs (pma#660)
|
# Backwards compatibility with old mkinitfs (pma#660)
|
||||||
suffix_flavor = f"-{flavor}"
|
suffix_flavor = f"-{flavor}"
|
||||||
|
@ -28,7 +29,7 @@ def odin(args: PmbArgs, flavor, folder: Path):
|
||||||
suffix_flavor = ""
|
suffix_flavor = ""
|
||||||
|
|
||||||
# Validate method
|
# Validate method
|
||||||
method = args.deviceinfo["flash_method"]
|
method = deviceinfo["flash_method"]
|
||||||
if not method.startswith("heimdall-"):
|
if not method.startswith("heimdall-"):
|
||||||
raise RuntimeError("An odin flashable tar is not supported"
|
raise RuntimeError("An odin flashable tar is not supported"
|
||||||
f" for the flash method '{method}' specified"
|
f" for the flash method '{method}' specified"
|
||||||
|
@ -36,10 +37,8 @@ def odin(args: PmbArgs, flavor, folder: Path):
|
||||||
" Only 'heimdall' methods are supported.")
|
" Only 'heimdall' methods are supported.")
|
||||||
|
|
||||||
# Partitions
|
# Partitions
|
||||||
partition_kernel = \
|
partition_kernel = deviceinfo["flash_heimdall_partition_kernel"] or "KERNEL"
|
||||||
args.deviceinfo["flash_heimdall_partition_kernel"] or "KERNEL"
|
partition_initfs = deviceinfo["flash_heimdall_partition_initfs"] or "RECOVERY"
|
||||||
partition_initfs = \
|
|
||||||
args.deviceinfo["flash_heimdall_partition_initfs"] or "RECOVERY"
|
|
||||||
|
|
||||||
# Temporary folder
|
# Temporary folder
|
||||||
temp_folder = "/tmp/odin-flashable-tar"
|
temp_folder = "/tmp/odin-flashable-tar"
|
||||||
|
@ -49,12 +48,12 @@ def odin(args: PmbArgs, flavor, folder: Path):
|
||||||
# Odin flashable tar generation script
|
# Odin flashable tar generation script
|
||||||
# (because redirecting stdin/stdout is not allowed
|
# (because redirecting stdin/stdout is not allowed
|
||||||
# in pmbootstrap's chroot/shell functions for security reasons)
|
# in pmbootstrap's chroot/shell functions for security reasons)
|
||||||
odin_script = Chroot(ChrootType.ROOTFS, args.devicesdhbfvhubsud) / "tmp/_odin.sh"
|
odin_script = Chroot(ChrootType.ROOTFS, context.device) / "tmp/_odin.sh"
|
||||||
with odin_script.open("w") as handle:
|
with odin_script.open("w") as handle:
|
||||||
odin_kernel_md5 = f"{partition_kernel}.bin.md5"
|
odin_kernel_md5 = f"{partition_kernel}.bin.md5"
|
||||||
odin_initfs_md5 = f"{partition_initfs}.bin.md5"
|
odin_initfs_md5 = f"{partition_initfs}.bin.md5"
|
||||||
odin_device_tar = f"{args.devicesdhbfvhubsud}.tar"
|
odin_device_tar = f"{context.device}.tar"
|
||||||
odin_device_tar_md5 = f"{args.devicesdhbfvhubsud}.tar.md5"
|
odin_device_tar_md5 = f"{context.device}.tar.md5"
|
||||||
|
|
||||||
handle.write(
|
handle.write(
|
||||||
"#!/bin/sh\n"
|
"#!/bin/sh\n"
|
||||||
|
@ -90,7 +89,7 @@ def odin(args: PmbArgs, flavor, folder: Path):
|
||||||
|
|
||||||
# Move Odin flashable tar to native chroot and cleanup temp folder
|
# Move Odin flashable tar to native chroot and cleanup temp folder
|
||||||
pmb.chroot.user(["mkdir", "-p", "/home/pmos/rootfs"])
|
pmb.chroot.user(["mkdir", "-p", "/home/pmos/rootfs"])
|
||||||
pmb.chroot.root(["mv", f"/mnt/rootfs_{args.devicesdhbfvhubsud}{temp_folder}"
|
pmb.chroot.root(["mv", f"/mnt/rootfs_{context.device}{temp_folder}"
|
||||||
f"/{odin_device_tar_md5}", "/home/pmos/rootfs/"]),
|
f"/{odin_device_tar_md5}", "/home/pmos/rootfs/"]),
|
||||||
pmb.chroot.root(["chown", "pmos:pmos",
|
pmb.chroot.root(["chown", "pmos:pmos",
|
||||||
f"/home/pmos/rootfs/{odin_device_tar_md5}"])
|
f"/home/pmos/rootfs/{odin_device_tar_md5}"])
|
||||||
|
@ -99,7 +98,7 @@ def odin(args: PmbArgs, flavor, folder: Path):
|
||||||
# Create the symlink
|
# Create the symlink
|
||||||
file = Chroot.native() / "home/pmos/rootfs" / odin_device_tar_md5
|
file = Chroot.native() / "home/pmos/rootfs" / odin_device_tar_md5
|
||||||
link = folder / odin_device_tar_md5
|
link = folder / odin_device_tar_md5
|
||||||
pmb.helpers.file.symlink(args, file, link)
|
pmb.helpers.file.symlink(file, link)
|
||||||
|
|
||||||
# Display a readable message
|
# Display a readable message
|
||||||
msg = f" * {odin_device_tar_md5}"
|
msg = f" * {odin_device_tar_md5}"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
from pmb.core.context import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List
|
from typing import List
|
||||||
|
@ -18,6 +19,9 @@ def symlinks(args: PmbArgs, flavor, folder: Path):
|
||||||
"""
|
"""
|
||||||
Create convenience symlinks to the rootfs and boot files.
|
Create convenience symlinks to the rootfs and boot files.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
context = get_context()
|
||||||
|
arch = pmb.parse.deviceinfo(context.device)["arch"]
|
||||||
|
|
||||||
# Backwards compatibility with old mkinitfs (pma#660)
|
# Backwards compatibility with old mkinitfs (pma#660)
|
||||||
suffix = f"-{flavor}"
|
suffix = f"-{flavor}"
|
||||||
|
@ -35,28 +39,28 @@ def symlinks(args: PmbArgs, flavor, folder: Path):
|
||||||
f"uInitrd{suffix}": "Initramfs, legacy u-boot image format",
|
f"uInitrd{suffix}": "Initramfs, legacy u-boot image format",
|
||||||
f"uImage{suffix}": "Kernel, legacy u-boot image format",
|
f"uImage{suffix}": "Kernel, legacy u-boot image format",
|
||||||
f"vmlinuz{suffix}": "Linux kernel",
|
f"vmlinuz{suffix}": "Linux kernel",
|
||||||
f"{args.devicesdhbfvhubsud}.img": "Rootfs with partitions for /boot and /",
|
f"{context.device}.img": "Rootfs with partitions for /boot and /",
|
||||||
f"{args.devicesdhbfvhubsud}-boot.img": "Boot partition image",
|
f"{context.device}-boot.img": "Boot partition image",
|
||||||
f"{args.devicesdhbfvhubsud}-root.img": "Root partition image",
|
f"{context.device}-root.img": "Root partition image",
|
||||||
f"pmos-{args.devicesdhbfvhubsud}.zip": "Android recovery flashable zip",
|
f"pmos-{context.device}.zip": "Android recovery flashable zip",
|
||||||
"lk2nd.img": "Secondary Android bootloader",
|
"lk2nd.img": "Secondary Android bootloader",
|
||||||
}
|
}
|
||||||
|
|
||||||
# Generate a list of patterns
|
# Generate a list of patterns
|
||||||
chroot_native = Chroot.native()
|
chroot_native = Chroot.native()
|
||||||
path_boot = Chroot(ChrootType.ROOTFS, args.devicesdhbfvhubsud) / "boot"
|
path_boot = Chroot(ChrootType.ROOTFS, context.device) / "boot"
|
||||||
chroot_buildroot = Chroot.buildroot(args.deviceinfo['arch'])
|
chroot_buildroot = Chroot.buildroot(arch)
|
||||||
files: List[Path] = [
|
files: List[Path] = [
|
||||||
path_boot / f"boot.img{suffix}",
|
path_boot / f"boot.img{suffix}",
|
||||||
path_boot / f"uInitrd{suffix}",
|
path_boot / f"uInitrd{suffix}",
|
||||||
path_boot / f"uImage{suffix}",
|
path_boot / f"uImage{suffix}",
|
||||||
path_boot / f"vmlinuz{suffix}",
|
path_boot / f"vmlinuz{suffix}",
|
||||||
path_boot / "dtbo.img",
|
path_boot / "dtbo.img",
|
||||||
chroot_native / "home/pmos/rootfs" / f"{args.devicesdhbfvhubsud}.img",
|
chroot_native / "home/pmos/rootfs" / f"{context.device}.img",
|
||||||
chroot_native / "home/pmos/rootfs" / f"{args.devicesdhbfvhubsud}-boot.img",
|
chroot_native / "home/pmos/rootfs" / f"{context.device}-boot.img",
|
||||||
chroot_native / "home/pmos/rootfs" / f"{args.devicesdhbfvhubsud}-root.img",
|
chroot_native / "home/pmos/rootfs" / f"{context.device}-root.img",
|
||||||
chroot_buildroot / "var/libpostmarketos-android-recovery-installer" /
|
chroot_buildroot / "var/libpostmarketos-android-recovery-installer" /
|
||||||
f"pmos-{args.devicesdhbfvhubsud}.zip",
|
f"pmos-{context.device}.zip",
|
||||||
path_boot / "lk2nd.img"
|
path_boot / "lk2nd.img"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -73,4 +77,4 @@ def symlinks(args: PmbArgs, flavor, folder: Path):
|
||||||
msg += " (" + info[basename] + ")"
|
msg += " (" + info[basename] + ")"
|
||||||
logging.info(msg)
|
logging.info(msg)
|
||||||
|
|
||||||
pmb.helpers.file.symlink(args, file, link)
|
pmb.helpers.file.symlink(file, link)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
from typing import Dict
|
||||||
|
from pmb.core.context import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
|
|
||||||
import pmb.config
|
import pmb.config
|
||||||
|
@ -15,106 +17,93 @@ import pmb.parse.kconfig
|
||||||
from pmb.core import Chroot, ChrootType
|
from pmb.core import Chroot, ChrootType
|
||||||
|
|
||||||
|
|
||||||
def kernel(args: PmbArgs):
|
def kernel(device: str, deviceinfo: Dict[str, str], boot: bool = False, autoinstall: bool = False):
|
||||||
# Rebuild the initramfs, just to make sure (see #69)
|
# Rebuild the initramfs, just to make sure (see #69)
|
||||||
flavor = pmb.helpers.frontend._parse_flavor(args, args.autoinstall)
|
flavor = pmb.helpers.frontend._parse_flavor(device, autoinstall)
|
||||||
if args.autoinstall:
|
if autoinstall:
|
||||||
pmb.chroot.initfs.build(args, flavor, Chroot(ChrootType.ROOTFS, args.devicesdhbfvhubsud))
|
pmb.chroot.initfs.build(flavor, Chroot(ChrootType.ROOTFS, device))
|
||||||
|
|
||||||
# Check kernel config
|
# Check kernel config
|
||||||
pmb.parse.kconfig.check(args, flavor, must_exist=False)
|
pmb.parse.kconfig.check(flavor, must_exist=False)
|
||||||
|
|
||||||
# Generate the paths and run the flasher
|
# Generate the paths and run the flasher
|
||||||
if args.action_flasher == "boot":
|
if boot:
|
||||||
logging.info("(native) boot " + flavor + " kernel")
|
logging.info("(native) boot " + flavor + " kernel")
|
||||||
pmb.flasher.run(args, "boot", flavor)
|
pmb.flasher.run(device, deviceinfo, "boot", flavor)
|
||||||
else:
|
else:
|
||||||
logging.info("(native) flash kernel " + flavor)
|
logging.info("(native) flash kernel " + flavor)
|
||||||
pmb.flasher.run(args, "flash_kernel", flavor)
|
pmb.flasher.run(device, deviceinfo, "flash_kernel", flavor)
|
||||||
logging.info("You will get an IP automatically assigned to your "
|
logging.info("You will get an IP automatically assigned to your "
|
||||||
"USB interface shortly.")
|
"USB interface shortly.")
|
||||||
logging.info("Then you can connect to your device using ssh after pmOS has"
|
logging.info("Then you can connect to your device using ssh after pmOS has"
|
||||||
" booted:")
|
" booted:")
|
||||||
logging.info("ssh {}@{}".format(args.user, pmb.config.default_ip))
|
logging.info(f"ssh {get_context().config.user}@{pmb.config.default_ip}")
|
||||||
logging.info("NOTE: If you enabled full disk encryption, you should make"
|
logging.info("NOTE: If you enabled full disk encryption, you should make"
|
||||||
" sure that Unl0kr has been properly configured for your"
|
" sure that Unl0kr has been properly configured for your"
|
||||||
" device")
|
" device")
|
||||||
|
|
||||||
|
|
||||||
def list_flavors(args: PmbArgs):
|
def list_flavors(device: str):
|
||||||
suffix = Chroot(ChrootType.ROOTFS, args.devicesdhbfvhubsud)
|
chroot = Chroot(ChrootType.ROOTFS, device)
|
||||||
logging.info(f"({suffix}) installed kernel flavors:")
|
logging.info(f"({chroot}) installed kernel flavors:")
|
||||||
logging.info("* " + pmb.chroot.other.kernel_flavor_installed(suffix))
|
logging.info("* " + pmb.chroot.other.kernel_flavor_installed(chroot))
|
||||||
|
|
||||||
|
|
||||||
def rootfs(args: PmbArgs):
|
def rootfs(device: str, deviceinfo: Dict[str, str], method: str):
|
||||||
method = args.flash_method or args.deviceinfo["flash_method"]
|
|
||||||
|
|
||||||
# Generate rootfs, install flasher
|
# Generate rootfs, install flasher
|
||||||
suffix = ".img"
|
suffix = ".img"
|
||||||
if pmb.config.flashers.get(method, {}).get("split", False):
|
if pmb.config.flashers.get(method, {}).get("split", False):
|
||||||
suffix = "-root.img"
|
suffix = "-root.img"
|
||||||
|
|
||||||
img_path = Chroot.native() / "home/pmos/rootfs" / f"{args.devicesdhbfvhubsud}{suffix}"
|
img_path = Chroot.native() / "home/pmos/rootfs" / f"{device}{suffix}"
|
||||||
if not img_path.exists():
|
if not img_path.exists():
|
||||||
raise RuntimeError("The rootfs has not been generated yet, please run"
|
raise RuntimeError("The rootfs has not been generated yet, please run"
|
||||||
" 'pmbootstrap install' first.")
|
" 'pmbootstrap install' first.")
|
||||||
|
|
||||||
# Do not flash if using fastboot & image is too large
|
# Do not flash if using fastboot & image is too large
|
||||||
if method.startswith("fastboot") \
|
if method.startswith("fastboot") \
|
||||||
and args.deviceinfo["flash_fastboot_max_size"]:
|
and deviceinfo["flash_fastboot_max_size"]:
|
||||||
img_size = img_path.stat().st_size / 1024**2
|
img_size = img_path.stat().st_size / 1024**2
|
||||||
max_size = int(args.deviceinfo["flash_fastboot_max_size"])
|
max_size = int(deviceinfo["flash_fastboot_max_size"])
|
||||||
if img_size > max_size:
|
if img_size > max_size:
|
||||||
raise RuntimeError("The rootfs is too large for fastboot to"
|
raise RuntimeError("The rootfs is too large for fastboot to"
|
||||||
" flash.")
|
" flash.")
|
||||||
|
|
||||||
# Run the flasher
|
# Run the flasher
|
||||||
logging.info("(native) flash rootfs image")
|
logging.info("(native) flash rootfs image")
|
||||||
pmb.flasher.run(args, "flash_rootfs")
|
pmb.flasher.run(device, deviceinfo, "flash_rootfs")
|
||||||
|
|
||||||
|
|
||||||
def flash_vbmeta(args: PmbArgs):
|
def list_devices(device, deviceinfo):
|
||||||
logging.info("(native) flash vbmeta.img with verity disabled flag")
|
pmb.flasher.run(device, deviceinfo, "list_devices")
|
||||||
pmb.flasher.run(args, "flash_vbmeta")
|
|
||||||
|
|
||||||
|
|
||||||
def flash_dtbo(args: PmbArgs):
|
def sideload(device: str, deviceinfo: Dict[str, str]):
|
||||||
logging.info("(native) flash dtbo image")
|
|
||||||
pmb.flasher.run(args, "flash_dtbo")
|
|
||||||
|
|
||||||
|
|
||||||
def list_devices(args: PmbArgs):
|
|
||||||
pmb.flasher.run(args, "list_devices")
|
|
||||||
|
|
||||||
|
|
||||||
def sideload(args: PmbArgs):
|
|
||||||
# Install depends
|
# Install depends
|
||||||
pmb.flasher.install_depends(args)
|
pmb.flasher.install_depends()
|
||||||
|
|
||||||
# Mount the buildroot
|
# Mount the buildroot
|
||||||
chroot = Chroot.buildroot(args.deviceinfo["arch"])
|
chroot = Chroot.buildroot(deviceinfo["arch"])
|
||||||
mountpoint = "/mnt/" / chroot
|
mountpoint = "/mnt/" / chroot
|
||||||
pmb.helpers.mount.bind(chroot.path,
|
pmb.helpers.mount.bind(chroot.path,
|
||||||
Chroot.native().path / mountpoint)
|
Chroot.native().path / mountpoint)
|
||||||
|
|
||||||
# Missing recovery zip error
|
# Missing recovery zip error
|
||||||
if not (Chroot.native() / mountpoint / "/var/lib/postmarketos-android-recovery-installer"
|
if not (Chroot.native() / mountpoint / "/var/lib/postmarketos-android-recovery-installer"
|
||||||
/ f"pmos-{args.devicesdhbfvhubsud}.zip").exists():
|
/ f"pmos-{device}.zip").exists():
|
||||||
raise RuntimeError("The recovery zip has not been generated yet,"
|
raise RuntimeError("The recovery zip has not been generated yet,"
|
||||||
" please run 'pmbootstrap install' with the"
|
" please run 'pmbootstrap install' with the"
|
||||||
" '--android-recovery-zip' parameter first!")
|
" '--android-recovery-zip' parameter first!")
|
||||||
|
|
||||||
pmb.flasher.run(args, "sideload")
|
pmb.flasher.run(device, deviceinfo, "sideload")
|
||||||
|
|
||||||
|
|
||||||
def flash_lk2nd(args: PmbArgs):
|
def flash_lk2nd(device: str, deviceinfo: Dict[str, str], method: str):
|
||||||
method = args.flash_method or args.deviceinfo["flash_method"]
|
|
||||||
if method == "fastboot":
|
if method == "fastboot":
|
||||||
# In the future this could be expanded to use "fastboot flash lk2nd $img"
|
# In the future this could be expanded to use "fastboot flash lk2nd $img"
|
||||||
# which reflashes/updates lk2nd from itself. For now let the user handle this
|
# which reflashes/updates lk2nd from itself. For now let the user handle this
|
||||||
# manually since supporting the codepath with heimdall requires more effort.
|
# manually since supporting the codepath with heimdall requires more effort.
|
||||||
pmb.flasher.init(args)
|
pmb.flasher.init(device)
|
||||||
logging.info("(native) checking current fastboot product")
|
logging.info("(native) checking current fastboot product")
|
||||||
output = pmb.chroot.root(["fastboot", "getvar", "product"],
|
output = pmb.chroot.root(["fastboot", "getvar", "product"],
|
||||||
output="interactive", output_return=True)
|
output="interactive", output_return=True)
|
||||||
|
@ -125,7 +114,7 @@ def flash_lk2nd(args: PmbArgs):
|
||||||
" bootloader mode to re-flash lk2nd.")
|
" bootloader mode to re-flash lk2nd.")
|
||||||
|
|
||||||
# Get the lk2nd package (which is a dependency of the device package)
|
# Get the lk2nd package (which is a dependency of the device package)
|
||||||
device_pkg = f"device-{args.devicesdhbfvhubsud}"
|
device_pkg = f"device-{device}"
|
||||||
apkbuild = pmb.helpers.pmaports.get(device_pkg)
|
apkbuild = pmb.helpers.pmaports.get(device_pkg)
|
||||||
lk2nd_pkg = None
|
lk2nd_pkg = None
|
||||||
for dep in apkbuild["depends"]:
|
for dep in apkbuild["depends"]:
|
||||||
|
@ -136,16 +125,19 @@ def flash_lk2nd(args: PmbArgs):
|
||||||
if not lk2nd_pkg:
|
if not lk2nd_pkg:
|
||||||
raise RuntimeError(f"{device_pkg} does not depend on any lk2nd package")
|
raise RuntimeError(f"{device_pkg} does not depend on any lk2nd package")
|
||||||
|
|
||||||
suffix = Chroot(ChrootType.ROOTFS, args.devicesdhbfvhubsud)
|
suffix = Chroot(ChrootType.ROOTFS, device)
|
||||||
pmb.chroot.apk.install([lk2nd_pkg], suffix)
|
pmb.chroot.apk.install([lk2nd_pkg], suffix)
|
||||||
|
|
||||||
logging.info("(native) flash lk2nd image")
|
logging.info("(native) flash lk2nd image")
|
||||||
pmb.flasher.run(args, "flash_lk2nd")
|
pmb.flasher.run(device, deviceinfo, "flash_lk2nd")
|
||||||
|
|
||||||
|
|
||||||
def frontend(args: PmbArgs):
|
def frontend(args: PmbArgs):
|
||||||
|
context = get_context()
|
||||||
action = args.action_flasher
|
action = args.action_flasher
|
||||||
method = args.flash_method or args.deviceinfo["flash_method"]
|
device = context.device
|
||||||
|
deviceinfo = pmb.parse.deviceinfo()
|
||||||
|
method = args.flash_method or deviceinfo["flash_method"]
|
||||||
|
|
||||||
if method == "none" and action in ["boot", "flash_kernel", "flash_rootfs",
|
if method == "none" and action in ["boot", "flash_kernel", "flash_rootfs",
|
||||||
"flash_lk2nd"]:
|
"flash_lk2nd"]:
|
||||||
|
@ -153,18 +145,20 @@ def frontend(args: PmbArgs):
|
||||||
return
|
return
|
||||||
|
|
||||||
if action in ["boot", "flash_kernel"]:
|
if action in ["boot", "flash_kernel"]:
|
||||||
kernel(args)
|
kernel(device, deviceinfo)
|
||||||
elif action == "flash_rootfs":
|
elif action == "flash_rootfs":
|
||||||
rootfs(args)
|
rootfs(device, deviceinfo, method)
|
||||||
elif action == "flash_vbmeta":
|
elif action == "flash_vbmeta":
|
||||||
flash_vbmeta(args)
|
logging.info("(native) flash vbmeta.img with verity disabled flag")
|
||||||
|
pmb.flasher.run(device, deviceinfo, "flash_vbmeta")
|
||||||
elif action == "flash_dtbo":
|
elif action == "flash_dtbo":
|
||||||
flash_dtbo(args)
|
logging.info("(native) flash dtbo image")
|
||||||
|
pmb.flasher.run(device, deviceinfo, "flash_dtbo")
|
||||||
elif action == "flash_lk2nd":
|
elif action == "flash_lk2nd":
|
||||||
flash_lk2nd(args)
|
flash_lk2nd(device, deviceinfo, method)
|
||||||
elif action == "list_flavors":
|
elif action == "list_flavors":
|
||||||
list_flavors(args)
|
list_flavors(device)
|
||||||
elif action == "list_devices":
|
elif action == "list_devices":
|
||||||
list_devices(args)
|
list_devices(device, deviceinfo)
|
||||||
elif action == "sideload":
|
elif action == "sideload":
|
||||||
sideload(args)
|
sideload(device, deviceinfo)
|
||||||
|
|
|
@ -5,15 +5,18 @@ import pmb.config
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
from pmb.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.mount
|
import pmb.helpers.mount
|
||||||
|
import pmb.helpers.args
|
||||||
from pmb.helpers.mount import mount_device_rootfs
|
from pmb.helpers.mount import mount_device_rootfs
|
||||||
from pmb.core import Chroot, ChrootType
|
from pmb.core import Chroot, ChrootType
|
||||||
|
|
||||||
|
|
||||||
def install_depends(args: PmbArgs):
|
def install_depends() -> None:
|
||||||
|
args: PmbArgs = pmb.helpers.args.please_i_really_need_args()
|
||||||
if hasattr(args, 'flash_method'):
|
if hasattr(args, 'flash_method'):
|
||||||
method = args.flash_method or args.deviceinfo["flash_method"]
|
method = args.flash_method
|
||||||
else:
|
|
||||||
method = args.deviceinfo["flash_method"]
|
if not method:
|
||||||
|
method = pmb.parse.deviceinfo()["flash_method"]
|
||||||
|
|
||||||
if method not in pmb.config.flashers:
|
if method not in pmb.config.flashers:
|
||||||
raise RuntimeError(f"Flash method {method} is not supported by the"
|
raise RuntimeError(f"Flash method {method} is not supported by the"
|
||||||
|
@ -43,12 +46,12 @@ def install_depends(args: PmbArgs):
|
||||||
pmb.chroot.apk.install(depends, Chroot.native())
|
pmb.chroot.apk.install(depends, Chroot.native())
|
||||||
|
|
||||||
|
|
||||||
def init(args: PmbArgs):
|
def init(device: str):
|
||||||
install_depends(args)
|
install_depends()
|
||||||
|
|
||||||
# Mount folders from host system
|
# Mount folders from host system
|
||||||
for folder in pmb.config.flash_mount_bind:
|
for folder in pmb.config.flash_mount_bind:
|
||||||
pmb.helpers.mount.bind(folder, Chroot.native() / folder)
|
pmb.helpers.mount.bind(folder, Chroot.native() / folder)
|
||||||
|
|
||||||
# Mount device chroot inside native chroot (required for kernel/ramdisk)
|
# Mount device chroot inside native chroot (required for kernel/ramdisk)
|
||||||
mount_device_rootfs(args, Chroot(ChrootType.ROOTFS, args.devicesdhbfvhubsud))
|
mount_device_rootfs(Chroot(ChrootType.ROOTFS, device))
|
||||||
|
|
|
@ -1,26 +1,31 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
from typing import Dict
|
||||||
from pmb.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.flasher
|
import pmb.flasher
|
||||||
import pmb.chroot.initfs
|
import pmb.chroot.initfs
|
||||||
|
import pmb.helpers.args
|
||||||
|
|
||||||
|
|
||||||
def check_partition_blacklist(args: PmbArgs, key, value):
|
def check_partition_blacklist(args: PmbArgs, deviceinfo: Dict[str, str], key, value):
|
||||||
if not key.startswith("$PARTITION_"):
|
if not key.startswith("$PARTITION_"):
|
||||||
return
|
return
|
||||||
|
|
||||||
name = args.deviceinfo["name"]
|
name = deviceinfo["name"]
|
||||||
if value in args.deviceinfo["partition_blacklist"].split(","):
|
if value in deviceinfo["partition_blacklist"].split(","):
|
||||||
raise RuntimeError("'" + value + "'" + " partition is blacklisted " +
|
raise RuntimeError("'" + value + "'" + " partition is blacklisted " +
|
||||||
"from being flashed! See the " + name + " device " +
|
"from being flashed! See the " + name + " device " +
|
||||||
"wiki page for more information.")
|
"wiki page for more information.")
|
||||||
|
|
||||||
|
|
||||||
def run(args: PmbArgs, action, flavor=None):
|
def run(device: str, deviceinfo: Dict[str, str], action, flavor=None):
|
||||||
pmb.flasher.init(args)
|
pmb.flasher.init(device)
|
||||||
|
|
||||||
|
# FIXME: handle argparsing and pass in only the args we need.
|
||||||
|
args = pmb.helpers.args.please_i_really_need_args()
|
||||||
|
|
||||||
# Verify action
|
# Verify action
|
||||||
method = args.flash_method or args.deviceinfo["flash_method"]
|
method = args.flash_method or deviceinfo["flash_method"]
|
||||||
cfg = pmb.config.flashers[method]
|
cfg = pmb.config.flashers[method]
|
||||||
if not isinstance(cfg["actions"], dict):
|
if not isinstance(cfg["actions"], dict):
|
||||||
raise TypeError(f"Flashers misconfigured! {method} key 'actions' should be a dictionary")
|
raise TypeError(f"Flashers misconfigured! {method} key 'actions' should be a dictionary")
|
||||||
|
@ -74,7 +79,7 @@ def run(args: PmbArgs, action, flavor=None):
|
||||||
" but the value for this variable"
|
" but the value for this variable"
|
||||||
" is None! Is that missing in your"
|
" is None! Is that missing in your"
|
||||||
" deviceinfo?")
|
" deviceinfo?")
|
||||||
check_partition_blacklist(args, key, value)
|
check_partition_blacklist(args, deviceinfo, key, value)
|
||||||
command[i] = command[i].replace(key, value)
|
command[i] = command[i].replace(key, value)
|
||||||
|
|
||||||
# Remove empty strings
|
# Remove empty strings
|
||||||
|
|
|
@ -2,15 +2,18 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
|
from pmb.core.context import get_context
|
||||||
from pmb.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
|
|
||||||
|
|
||||||
def variables(args: PmbArgs, flavor, method):
|
def variables(args: PmbArgs, flavor, method):
|
||||||
_cmdline = args.deviceinfo["kernel_cmdline"] or ""
|
device = get_context().config.device
|
||||||
|
deviceinfo = pmb.parse.deviceinfo()
|
||||||
|
_cmdline = deviceinfo["kernel_cmdline"] or ""
|
||||||
if "cmdline" in args and args.cmdline:
|
if "cmdline" in args and args.cmdline:
|
||||||
_cmdline = args.cmdline
|
_cmdline = args.cmdline
|
||||||
|
|
||||||
flash_pagesize = args.deviceinfo['flash_pagesize']
|
flash_pagesize = deviceinfo['flash_pagesize']
|
||||||
|
|
||||||
# TODO Remove _partition_system deviceinfo support once pmaports has been
|
# TODO Remove _partition_system deviceinfo support once pmaports has been
|
||||||
# updated and minimum pmbootstrap version bumped.
|
# updated and minimum pmbootstrap version bumped.
|
||||||
|
@ -20,39 +23,39 @@ def variables(args: PmbArgs, flavor, method):
|
||||||
_partition_rootfs: Optional[str]
|
_partition_rootfs: Optional[str]
|
||||||
|
|
||||||
if method.startswith("fastboot"):
|
if method.startswith("fastboot"):
|
||||||
_partition_kernel = args.deviceinfo["flash_fastboot_partition_kernel"]\
|
_partition_kernel = deviceinfo["flash_fastboot_partition_kernel"]\
|
||||||
or "boot"
|
or "boot"
|
||||||
_partition_rootfs = args.deviceinfo["flash_fastboot_partition_rootfs"]\
|
_partition_rootfs = deviceinfo["flash_fastboot_partition_rootfs"]\
|
||||||
or args.deviceinfo["flash_fastboot_partition_system"] or "userdata"
|
or deviceinfo["flash_fastboot_partition_system"] or "userdata"
|
||||||
_partition_vbmeta = args.deviceinfo["flash_fastboot_partition_vbmeta"]\
|
_partition_vbmeta = deviceinfo["flash_fastboot_partition_vbmeta"]\
|
||||||
or None
|
or None
|
||||||
_partition_dtbo = args.deviceinfo["flash_fastboot_partition_dtbo"]\
|
_partition_dtbo = deviceinfo["flash_fastboot_partition_dtbo"]\
|
||||||
or None
|
or None
|
||||||
# Require that the partitions are specified in deviceinfo for now
|
# Require that the partitions are specified in deviceinfo for now
|
||||||
elif method.startswith("rkdeveloptool"):
|
elif method.startswith("rkdeveloptool"):
|
||||||
_partition_kernel = args.deviceinfo["flash_rk_partition_kernel"]\
|
_partition_kernel = deviceinfo["flash_rk_partition_kernel"]\
|
||||||
or None
|
or None
|
||||||
_partition_rootfs = args.deviceinfo["flash_rk_partition_rootfs"]\
|
_partition_rootfs = deviceinfo["flash_rk_partition_rootfs"]\
|
||||||
or args.deviceinfo["flash_rk_partition_system"] or None
|
or deviceinfo["flash_rk_partition_system"] or None
|
||||||
_partition_vbmeta = None
|
_partition_vbmeta = None
|
||||||
_partition_dtbo = None
|
_partition_dtbo = None
|
||||||
elif method.startswith("mtkclient"):
|
elif method.startswith("mtkclient"):
|
||||||
_partition_kernel = args.deviceinfo["flash_mtkclient_partition_kernel"]\
|
_partition_kernel = deviceinfo["flash_mtkclient_partition_kernel"]\
|
||||||
or "boot"
|
or "boot"
|
||||||
_partition_rootfs = args.deviceinfo["flash_mtkclient_partition_rootfs"]\
|
_partition_rootfs = deviceinfo["flash_mtkclient_partition_rootfs"]\
|
||||||
or "userdata"
|
or "userdata"
|
||||||
_partition_vbmeta = args.deviceinfo["flash_mtkclient_partition_vbmeta"]\
|
_partition_vbmeta = deviceinfo["flash_mtkclient_partition_vbmeta"]\
|
||||||
or None
|
or None
|
||||||
_partition_dtbo = args.deviceinfo["flash_mtkclient_partition_dtbo"]\
|
_partition_dtbo = deviceinfo["flash_mtkclient_partition_dtbo"]\
|
||||||
or None
|
or None
|
||||||
else:
|
else:
|
||||||
_partition_kernel = args.deviceinfo["flash_heimdall_partition_kernel"]\
|
_partition_kernel = deviceinfo["flash_heimdall_partition_kernel"]\
|
||||||
or "KERNEL"
|
or "KERNEL"
|
||||||
_partition_rootfs = args.deviceinfo["flash_heimdall_partition_rootfs"]\
|
_partition_rootfs = deviceinfo["flash_heimdall_partition_rootfs"]\
|
||||||
or args.deviceinfo["flash_heimdall_partition_system"] or "SYSTEM"
|
or deviceinfo["flash_heimdall_partition_system"] or "SYSTEM"
|
||||||
_partition_vbmeta = args.deviceinfo["flash_heimdall_partition_vbmeta"]\
|
_partition_vbmeta = deviceinfo["flash_heimdall_partition_vbmeta"]\
|
||||||
or None
|
or None
|
||||||
_partition_dtbo = args.deviceinfo["flash_heimdall_partition_dtbo"]\
|
_partition_dtbo = deviceinfo["flash_heimdall_partition_dtbo"]\
|
||||||
or None
|
or None
|
||||||
|
|
||||||
if "partition" in args and args.partition:
|
if "partition" in args and args.partition:
|
||||||
|
@ -64,7 +67,7 @@ def variables(args: PmbArgs, flavor, method):
|
||||||
_partition_dtbo = args.partition
|
_partition_dtbo = args.partition
|
||||||
|
|
||||||
_dtb = ""
|
_dtb = ""
|
||||||
if args.deviceinfo["append_dtb"] == "true":
|
if deviceinfo["append_dtb"] == "true":
|
||||||
_dtb = "-dtb"
|
_dtb = "-dtb"
|
||||||
|
|
||||||
_no_reboot = ""
|
_no_reboot = ""
|
||||||
|
@ -76,23 +79,23 @@ def variables(args: PmbArgs, flavor, method):
|
||||||
_resume = "--resume"
|
_resume = "--resume"
|
||||||
|
|
||||||
vars = {
|
vars = {
|
||||||
"$BOOT": "/mnt/rootfs_" + args.devicesdhbfvhubsud + "/boot",
|
"$BOOT": "/mnt/rootfs_" + device + "/boot",
|
||||||
"$DTB": _dtb,
|
"$DTB": _dtb,
|
||||||
"$IMAGE_SPLIT_BOOT": "/home/pmos/rootfs/" + args.devicesdhbfvhubsud + "-boot.img",
|
"$IMAGE_SPLIT_BOOT": "/home/pmos/rootfs/" + device + "-boot.img",
|
||||||
"$IMAGE_SPLIT_ROOT": "/home/pmos/rootfs/" + args.devicesdhbfvhubsud + "-root.img",
|
"$IMAGE_SPLIT_ROOT": "/home/pmos/rootfs/" + device + "-root.img",
|
||||||
"$IMAGE": "/home/pmos/rootfs/" + args.devicesdhbfvhubsud + ".img",
|
"$IMAGE": "/home/pmos/rootfs/" + device + ".img",
|
||||||
"$KERNEL_CMDLINE": _cmdline,
|
"$KERNEL_CMDLINE": _cmdline,
|
||||||
"$PARTITION_KERNEL": _partition_kernel,
|
"$PARTITION_KERNEL": _partition_kernel,
|
||||||
"$PARTITION_INITFS": args.deviceinfo[
|
"$PARTITION_INITFS": deviceinfo[
|
||||||
"flash_heimdall_partition_initfs"] or "RECOVERY",
|
"flash_heimdall_partition_initfs"] or "RECOVERY",
|
||||||
"$PARTITION_ROOTFS": _partition_rootfs,
|
"$PARTITION_ROOTFS": _partition_rootfs,
|
||||||
"$PARTITION_VBMETA": _partition_vbmeta,
|
"$PARTITION_VBMETA": _partition_vbmeta,
|
||||||
"$PARTITION_DTBO": _partition_dtbo,
|
"$PARTITION_DTBO": _partition_dtbo,
|
||||||
"$FLASH_PAGESIZE": flash_pagesize,
|
"$FLASH_PAGESIZE": flash_pagesize,
|
||||||
"$RECOVERY_ZIP": "/mnt/buildroot_" + args.deviceinfo["arch"] +
|
"$RECOVERY_ZIP": "/mnt/buildroot_" + deviceinfo["arch"] +
|
||||||
"/var/lib/postmarketos-android-recovery-installer"
|
"/var/lib/postmarketos-android-recovery-installer"
|
||||||
"/pmos-" + args.devicesdhbfvhubsud + ".zip",
|
"/pmos-" + device + ".zip",
|
||||||
"$UUU_SCRIPT": "/mnt/rootfs_" + args.deviceinfo["codename"] +
|
"$UUU_SCRIPT": "/mnt/rootfs_" + deviceinfo["codename"] +
|
||||||
"/usr/share/uuu/flash_script.lst",
|
"/usr/share/uuu/flash_script.lst",
|
||||||
"$NO_REBOOT": _no_reboot,
|
"$NO_REBOOT": _no_reboot,
|
||||||
"$RESUME": _resume
|
"$RESUME": _resume
|
||||||
|
|
|
@ -4,7 +4,7 @@ import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Sequence
|
from typing import List, Sequence
|
||||||
|
|
||||||
import pmb.chroot.run
|
import pmb.chroot
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
from pmb.types import PathString, PmbArgs
|
from pmb.types import PathString, PmbArgs
|
||||||
import pmb.helpers.cli
|
import pmb.helpers.cli
|
||||||
|
|
|
@ -275,7 +275,7 @@ def upgrade(args: PmbArgs, pkgname, git=True, stable=True) -> None:
|
||||||
|
|
||||||
def upgrade_all(args: PmbArgs) -> None:
|
def upgrade_all(args: PmbArgs) -> None:
|
||||||
"""Upgrade all packages, based on args.all, args.all_git and args.all_stable."""
|
"""Upgrade all packages, based on args.all, args.all_git and args.all_stable."""
|
||||||
for pkgname in pmb.helpers.pmaports.get_list(args):
|
for pkgname in pmb.helpers.pmaports.get_list():
|
||||||
# Always ignore postmarketOS-specific packages that have no upstream
|
# Always ignore postmarketOS-specific packages that have no upstream
|
||||||
# source
|
# source
|
||||||
skip = False
|
skip = False
|
||||||
|
|
|
@ -48,7 +48,7 @@ __args: PmbArgs = PmbArgs()
|
||||||
code as well.
|
code as well.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
args.deviceinfo (e.g. {"name": "Mydevice", "arch": "armhf", ...})
|
deviceinfo (e.g. {"name": "Mydevice", "arch": "armhf", ...})
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,17 +82,17 @@ def check_pmaports_path(args: PmbArgs):
|
||||||
# setattr(args, key, Path(getattr(args, key)).expanduser())
|
# setattr(args, key, Path(getattr(args, key)).expanduser())
|
||||||
|
|
||||||
|
|
||||||
def add_deviceinfo(args: PmbArgs):
|
|
||||||
"""Add and verify the deviceinfo (only after initialization)"""
|
|
||||||
setattr(args, "deviceinfo", pmb.parse.deviceinfo())
|
|
||||||
|
|
||||||
|
|
||||||
def init(args: PmbArgs) -> PmbArgs:
|
def init(args: PmbArgs) -> PmbArgs:
|
||||||
global __args
|
global __args
|
||||||
# Basic initialization
|
# Basic initialization
|
||||||
config = pmb.config.load(args)
|
config = pmb.config.load(args)
|
||||||
# pmb.config.merge_with_args(args)
|
|
||||||
# replace_placeholders(args)
|
for key, value in vars(args).items():
|
||||||
|
if key.startswith("_"):
|
||||||
|
continue
|
||||||
|
if getattr(args, key, None) and hasattr(config, key):
|
||||||
|
print(f"Overriding config.{key} with {value}")
|
||||||
|
setattr(config, key, value)
|
||||||
|
|
||||||
# Configure runtime context
|
# Configure runtime context
|
||||||
context = Context(config)
|
context = Context(config)
|
||||||
|
@ -102,6 +102,8 @@ def init(args: PmbArgs) -> PmbArgs:
|
||||||
context.offline = args.offline
|
context.offline = args.offline
|
||||||
context.command = args.action
|
context.command = args.action
|
||||||
context.cross = args.cross
|
context.cross = args.cross
|
||||||
|
context.assume_yes = getattr(args, "assume_yes", False)
|
||||||
|
context.force = getattr(args, "force", False)
|
||||||
if args.mirrors_postmarketos:
|
if args.mirrors_postmarketos:
|
||||||
context.config.mirrors_postmarketos = args.mirrors_postmarketos
|
context.config.mirrors_postmarketos = args.mirrors_postmarketos
|
||||||
if args.mirror_alpine:
|
if args.mirror_alpine:
|
||||||
|
@ -121,9 +123,9 @@ def init(args: PmbArgs) -> PmbArgs:
|
||||||
if args.action not in ["init", "checksum", "config", "bootimg_analyze", "log",
|
if args.action not in ["init", "checksum", "config", "bootimg_analyze", "log",
|
||||||
"pull", "shutdown", "zap"]:
|
"pull", "shutdown", "zap"]:
|
||||||
pmb.config.pmaports.read_config()
|
pmb.config.pmaports.read_config()
|
||||||
add_deviceinfo(args)
|
|
||||||
pmb.helpers.git.parse_channels_cfg(config.aports)
|
pmb.helpers.git.parse_channels_cfg(config.aports)
|
||||||
context.device_arch = args.deviceinfo["arch"]
|
deviceinfo = pmb.parse.deviceinfo()
|
||||||
|
context.device_arch = deviceinfo["arch"]
|
||||||
|
|
||||||
# Remove attributes from args so they don't get used by mistake
|
# Remove attributes from args so they don't get used by mistake
|
||||||
delattr(args, "timeout")
|
delattr(args, "timeout")
|
||||||
|
@ -134,6 +136,10 @@ def init(args: PmbArgs) -> PmbArgs:
|
||||||
delattr(args, "aports")
|
delattr(args, "aports")
|
||||||
delattr(args, "mirrors_postmarketos")
|
delattr(args, "mirrors_postmarketos")
|
||||||
delattr(args, "mirror_alpine")
|
delattr(args, "mirror_alpine")
|
||||||
|
if hasattr(args, "force"):
|
||||||
|
delattr(args, "force")
|
||||||
|
if hasattr(args, "device"):
|
||||||
|
delattr(args, "device")
|
||||||
# args.work is deprecated!
|
# args.work is deprecated!
|
||||||
delattr(args, "work")
|
delattr(args, "work")
|
||||||
|
|
||||||
|
@ -142,7 +148,7 @@ def init(args: PmbArgs) -> PmbArgs:
|
||||||
if not key.startswith("_") and not key == "from_argparse":
|
if not key.startswith("_") and not key == "from_argparse":
|
||||||
setattr(__args, key, value)
|
setattr(__args, key, value)
|
||||||
|
|
||||||
print(json.dumps(__args.__dict__))
|
#print(json.dumps(__args.__dict__))
|
||||||
|
|
||||||
#sys.exit(0)
|
#sys.exit(0)
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ def is_older_than(path, seconds):
|
||||||
return lastmod + seconds < time.time()
|
return lastmod + seconds < time.time()
|
||||||
|
|
||||||
|
|
||||||
def symlink(args: PmbArgs, file: Path, link: Path):
|
def symlink(file: Path, link: Path):
|
||||||
"""Check if the symlink is already present, otherwise create it."""
|
"""Check if the symlink is already present, otherwise create it."""
|
||||||
if os.path.exists(link):
|
if os.path.exists(link):
|
||||||
if (os.path.islink(link) and
|
if (os.path.islink(link) and
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
import json
|
import json
|
||||||
from typing import List, Sequence
|
from typing import List, Sequence, Tuple
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
@ -40,7 +40,7 @@ import pmb.sideload
|
||||||
from pmb.core import ChrootType, Chroot, get_context
|
from pmb.core import ChrootType, Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def _parse_flavor(args: PmbArgs, autoinstall=True):
|
def _parse_flavor(device: str, autoinstall=True):
|
||||||
"""Verify the flavor argument if specified, or return a default value.
|
"""Verify the flavor argument if specified, or return a default value.
|
||||||
|
|
||||||
:param autoinstall: make sure that at least one kernel flavor is installed
|
:param autoinstall: make sure that at least one kernel flavor is installed
|
||||||
|
@ -49,7 +49,7 @@ def _parse_flavor(args: PmbArgs, autoinstall=True):
|
||||||
# identifier that is typically in the form
|
# identifier that is typically in the form
|
||||||
# "postmarketos-<manufacturer>-<device/chip>", e.g.
|
# "postmarketos-<manufacturer>-<device/chip>", e.g.
|
||||||
# "postmarketos-qcom-sdm845"
|
# "postmarketos-qcom-sdm845"
|
||||||
chroot = Chroot(ChrootType.ROOTFS, args.devicesdhbfvhubsud)
|
chroot = Chroot(ChrootType.ROOTFS, device)
|
||||||
flavor = pmb.chroot.other.kernel_flavor_installed(
|
flavor = pmb.chroot.other.kernel_flavor_installed(
|
||||||
chroot, autoinstall)
|
chroot, autoinstall)
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ def _parse_suffix(args: PmbArgs) -> Chroot:
|
||||||
return Chroot(ChrootType.ROOTFS, get_context().config.device)
|
return Chroot(ChrootType.ROOTFS, get_context().config.device)
|
||||||
elif args.buildroot:
|
elif args.buildroot:
|
||||||
if args.buildroot == "device":
|
if args.buildroot == "device":
|
||||||
return Chroot.buildroot(args.deviceinfo["arch"])
|
return Chroot.buildroot(pmb.parse.deviceinfo()["arch"])
|
||||||
else:
|
else:
|
||||||
return Chroot.buildroot(args.buildroot)
|
return Chroot.buildroot(args.buildroot)
|
||||||
elif args.suffix:
|
elif args.suffix:
|
||||||
|
@ -76,14 +76,14 @@ def _parse_suffix(args: PmbArgs) -> Chroot:
|
||||||
return Chroot(ChrootType.NATIVE)
|
return Chroot(ChrootType.NATIVE)
|
||||||
|
|
||||||
|
|
||||||
def _install_ondev_verify_no_rootfs(args: PmbArgs):
|
def _install_ondev_verify_no_rootfs(device: str, ondev_cp: List[Tuple[str, str]]):
|
||||||
chroot_dest = "/var/lib/rootfs.img"
|
chroot_dest = "/var/lib/rootfs.img"
|
||||||
dest = Chroot(ChrootType.INSTALLER, args.devicesdhbfvhubsud) / chroot_dest
|
dest = Chroot(ChrootType.INSTALLER, device) / chroot_dest
|
||||||
if dest.exists():
|
if dest.exists():
|
||||||
return
|
return
|
||||||
|
|
||||||
if args.ondev_cp:
|
if ondev_cp:
|
||||||
for _, chroot_dest_cp in args.ondev_cp:
|
for _, chroot_dest_cp in ondev_cp:
|
||||||
if chroot_dest_cp == chroot_dest:
|
if chroot_dest_cp == chroot_dest:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -112,14 +112,14 @@ def build(args: PmbArgs):
|
||||||
# Set src and force
|
# Set src and force
|
||||||
src = os.path.realpath(os.path.expanduser(args.src[0])) \
|
src = os.path.realpath(os.path.expanduser(args.src[0])) \
|
||||||
if args.src else None
|
if args.src else None
|
||||||
force = True if src else args.force
|
force = True if src else get_context().force
|
||||||
if src and not os.path.exists(src):
|
if src and not os.path.exists(src):
|
||||||
raise RuntimeError("Invalid path specified for --src: " + src)
|
raise RuntimeError("Invalid path specified for --src: " + src)
|
||||||
|
|
||||||
# Ensure repo_bootstrap is done for all arches we intend to build for
|
# Ensure repo_bootstrap is done for all arches we intend to build for
|
||||||
for package in args.packages:
|
for package in args.packages:
|
||||||
arch_package = args.arch or pmb.build.autodetect.arch(args, package)
|
arch_package = args.arch or pmb.build.autodetect.arch(args, package)
|
||||||
pmb.helpers.repo_bootstrap.require_bootstrap(args, arch_package,
|
pmb.helpers.repo_bootstrap.require_bootstrap(arch_package,
|
||||||
f"build {package} for {arch_package}")
|
f"build {package} for {arch_package}")
|
||||||
|
|
||||||
context = get_context()
|
context = get_context()
|
||||||
|
@ -134,8 +134,8 @@ def build(args: PmbArgs):
|
||||||
|
|
||||||
|
|
||||||
def build_init(args: PmbArgs):
|
def build_init(args: PmbArgs):
|
||||||
suffix = _parse_suffix(args)
|
chroot = _parse_suffix(args)
|
||||||
pmb.build.init(args, suffix)
|
pmb.build.init(chroot)
|
||||||
|
|
||||||
|
|
||||||
def checksum(args: PmbArgs):
|
def checksum(args: PmbArgs):
|
||||||
|
@ -148,7 +148,7 @@ def checksum(args: PmbArgs):
|
||||||
|
|
||||||
def sideload(args: PmbArgs):
|
def sideload(args: PmbArgs):
|
||||||
arch = args.arch
|
arch = args.arch
|
||||||
user = args.user
|
user = get_context().config.user
|
||||||
host = args.host
|
host = args.host
|
||||||
pmb.sideload.sideload(args, user, host, args.port, arch, args.install_key,
|
pmb.sideload.sideload(args, user, host, args.port, arch, args.install_key,
|
||||||
args.packages)
|
args.packages)
|
||||||
|
@ -156,25 +156,27 @@ def sideload(args: PmbArgs):
|
||||||
|
|
||||||
def netboot(args: PmbArgs):
|
def netboot(args: PmbArgs):
|
||||||
if args.action_netboot == "serve":
|
if args.action_netboot == "serve":
|
||||||
pmb.netboot.start_nbd_server(args)
|
device = get_context().config.device
|
||||||
|
pmb.netboot.start_nbd_server(device, args.replace)
|
||||||
|
|
||||||
|
|
||||||
def chroot(args: PmbArgs):
|
def chroot(args: PmbArgs):
|
||||||
# Suffix
|
# Suffix
|
||||||
suffix = _parse_suffix(args)
|
chroot = _parse_suffix(args)
|
||||||
if (args.user and suffix != Chroot.native() and
|
user = get_context().config.user
|
||||||
not suffix.type == ChrootType.BUILDROOT):
|
if (user and chroot != Chroot.native() and
|
||||||
|
not chroot.type == ChrootType.BUILDROOT):
|
||||||
raise RuntimeError("--user is only supported for native or"
|
raise RuntimeError("--user is only supported for native or"
|
||||||
" buildroot_* chroots.")
|
" buildroot_* chroots.")
|
||||||
if args.xauth and suffix != Chroot.native():
|
if args.xauth and chroot != Chroot.native():
|
||||||
raise RuntimeError("--xauth is only supported for native chroot.")
|
raise RuntimeError("--xauth is only supported for native chroot.")
|
||||||
|
|
||||||
# apk: check minimum version, install packages
|
# apk: check minimum version, install packages
|
||||||
pmb.chroot.apk.check_min_version(suffix)
|
pmb.chroot.apk.check_min_version(chroot)
|
||||||
if args.add:
|
if args.add:
|
||||||
pmb.chroot.apk.install(args.add.split(","), suffix)
|
pmb.chroot.apk.install(args.add.split(","), chroot)
|
||||||
|
|
||||||
pmb.chroot.init(suffix)
|
pmb.chroot.init(chroot)
|
||||||
|
|
||||||
# Xauthority
|
# Xauthority
|
||||||
env = {}
|
env = {}
|
||||||
|
@ -196,14 +198,14 @@ def chroot(args: PmbArgs):
|
||||||
size_root, size_reserve)
|
size_root, size_reserve)
|
||||||
|
|
||||||
# Run the command as user/root
|
# Run the command as user/root
|
||||||
if args.user:
|
if user:
|
||||||
logging.info(f"({suffix}) % su pmos -c '" +
|
logging.info(f"({chroot}) % su pmos -c '" +
|
||||||
" ".join(args.command) + "'")
|
" ".join(args.command) + "'")
|
||||||
pmb.chroot.user(args.command, suffix, output=args.output,
|
pmb.chroot.user(args.command, chroot, output=args.output,
|
||||||
env=env)
|
env=env)
|
||||||
else:
|
else:
|
||||||
logging.info(f"({suffix}) % " + " ".join(args.command))
|
logging.info(f"({chroot}) % " + " ".join(args.command))
|
||||||
pmb.chroot.root(args.command, suffix, output=args.output,
|
pmb.chroot.root(args.command, chroot, output=args.output,
|
||||||
env=env)
|
env=env)
|
||||||
|
|
||||||
|
|
||||||
|
@ -219,7 +221,7 @@ def config(args: PmbArgs):
|
||||||
raise RuntimeError("config --reset requires a name to be given.")
|
raise RuntimeError("config --reset requires a name to be given.")
|
||||||
def_value = getattr(Config(), args.name)
|
def_value = getattr(Config(), args.name)
|
||||||
setattr(config, args.name, def_value)
|
setattr(config, args.name, def_value)
|
||||||
logging.info(f"Config changed to default: {args.name}='{value}'")
|
logging.info(f"Config changed to default: {args.name}='{def_value}'")
|
||||||
pmb.config.save(args.config, config)
|
pmb.config.save(args.config, config)
|
||||||
elif args.value is not None:
|
elif args.value is not None:
|
||||||
setattr(config, args.name, args.value)
|
setattr(config, args.name, args.value)
|
||||||
|
@ -258,6 +260,9 @@ def initfs(args: PmbArgs):
|
||||||
|
|
||||||
|
|
||||||
def install(args: PmbArgs):
|
def install(args: PmbArgs):
|
||||||
|
config = get_context().config
|
||||||
|
device = config.device
|
||||||
|
deviceinfo = pmb.parse.deviceinfo(device)
|
||||||
if args.no_fde:
|
if args.no_fde:
|
||||||
logging.warning("WARNING: --no-fde is deprecated,"
|
logging.warning("WARNING: --no-fde is deprecated,"
|
||||||
" as it is now the default.")
|
" as it is now the default.")
|
||||||
|
@ -271,8 +276,8 @@ def install(args: PmbArgs):
|
||||||
raise ValueError("Installation using rsync"
|
raise ValueError("Installation using rsync"
|
||||||
" is not currently supported on btrfs filesystem.")
|
" is not currently supported on btrfs filesystem.")
|
||||||
|
|
||||||
pmb.helpers.repo_bootstrap.require_bootstrap(args, args.deviceinfo["arch"],
|
pmb.helpers.repo_bootstrap.require_bootstrap(deviceinfo["arch"],
|
||||||
f"do 'pmbootstrap install' for {args.deviceinfo['arch']}"
|
f"do 'pmbootstrap install' for {deviceinfo['arch']}"
|
||||||
" (deviceinfo_arch)")
|
" (deviceinfo_arch)")
|
||||||
|
|
||||||
# On-device installer checks
|
# On-device installer checks
|
||||||
|
@ -296,7 +301,7 @@ def install(args: PmbArgs):
|
||||||
raise ValueError("--on-device-installer cannot be combined with"
|
raise ValueError("--on-device-installer cannot be combined with"
|
||||||
" --filesystem")
|
" --filesystem")
|
||||||
|
|
||||||
if args.deviceinfo["cgpt_kpart"]:
|
if deviceinfo["cgpt_kpart"]:
|
||||||
raise ValueError("--on-device-installer cannot be used with"
|
raise ValueError("--on-device-installer cannot be used with"
|
||||||
" ChromeOS devices")
|
" ChromeOS devices")
|
||||||
else:
|
else:
|
||||||
|
@ -306,7 +311,7 @@ def install(args: PmbArgs):
|
||||||
raise ValueError("--no-rootfs can only be combined with --ondev."
|
raise ValueError("--no-rootfs can only be combined with --ondev."
|
||||||
" Do you mean --no-image?")
|
" Do you mean --no-image?")
|
||||||
if args.ondev_no_rootfs:
|
if args.ondev_no_rootfs:
|
||||||
_install_ondev_verify_no_rootfs(args)
|
_install_ondev_verify_no_rootfs(device, args.ondev_cp)
|
||||||
|
|
||||||
# On-device installer overrides
|
# On-device installer overrides
|
||||||
if args.on_device_installer:
|
if args.on_device_installer:
|
||||||
|
@ -315,15 +320,15 @@ def install(args: PmbArgs):
|
||||||
# a password for the user, disable SSH password authentication,
|
# a password for the user, disable SSH password authentication,
|
||||||
# optionally add a new user for SSH that must not have the same
|
# optionally add a new user for SSH that must not have the same
|
||||||
# username etc.)
|
# username etc.)
|
||||||
if args.user != "user":
|
if config.user != "user":
|
||||||
logging.warning(f"WARNING: custom username '{args.user}' will be"
|
logging.warning(f"WARNING: custom username '{config.user}' will be"
|
||||||
" replaced with 'user' for the on-device"
|
" replaced with 'user' for the on-device"
|
||||||
" installer.")
|
" installer.")
|
||||||
args.user = "user"
|
config.user = "user"
|
||||||
|
|
||||||
if not args.disk and args.split is None:
|
if not args.disk and args.split is None:
|
||||||
# Default to split if the flash method requires it
|
# Default to split if the flash method requires it
|
||||||
flasher = pmb.config.flashers.get(args.deviceinfo["flash_method"], {})
|
flasher = pmb.config.flashers.get(deviceinfo["flash_method"], {})
|
||||||
if flasher.get("split", False):
|
if flasher.get("split", False):
|
||||||
args.split = True
|
args.split = True
|
||||||
|
|
||||||
|
@ -345,10 +350,10 @@ def install(args: PmbArgs):
|
||||||
if not args.install_local_pkgs:
|
if not args.install_local_pkgs:
|
||||||
# Implies that we don't build outdated packages (overriding the answer
|
# Implies that we don't build outdated packages (overriding the answer
|
||||||
# in 'pmbootstrap init')
|
# in 'pmbootstrap init')
|
||||||
args.build_pkgs_on_install = False
|
config.build_pkgs_on_install = False
|
||||||
|
|
||||||
# Safest way to avoid installing local packages is having none
|
# Safest way to avoid installing local packages is having none
|
||||||
if (get_context().config.work / "packages").glob("*"):
|
if (config.work / "packages").glob("*"):
|
||||||
raise ValueError("--no-local-pkgs specified, but locally built"
|
raise ValueError("--no-local-pkgs specified, but locally built"
|
||||||
" packages found. Consider 'pmbootstrap zap -p'"
|
" packages found. Consider 'pmbootstrap zap -p'"
|
||||||
" to delete them.")
|
" to delete them.")
|
||||||
|
@ -443,7 +448,7 @@ def kconfig(args: PmbArgs):
|
||||||
skipped = 0
|
skipped = 0
|
||||||
packages.sort()
|
packages.sort()
|
||||||
for package in packages:
|
for package in packages:
|
||||||
if not args.force:
|
if not get_context().force:
|
||||||
pkgname = package if package.startswith("linux-") \
|
pkgname = package if package.startswith("linux-") \
|
||||||
else "linux-" + package
|
else "linux-" + package
|
||||||
aport = pmb.helpers.pmaports.find(pkgname)
|
aport = pmb.helpers.pmaports.find(pkgname)
|
||||||
|
@ -451,7 +456,7 @@ def kconfig(args: PmbArgs):
|
||||||
if "!pmb:kconfigcheck" in apkbuild["options"]:
|
if "!pmb:kconfigcheck" in apkbuild["options"]:
|
||||||
skipped += 1
|
skipped += 1
|
||||||
continue
|
continue
|
||||||
if not pmb.parse.kconfig.check(args, package, components_list,
|
if not pmb.parse.kconfig.check(package, components_list,
|
||||||
details=details):
|
details=details):
|
||||||
error = True
|
error = True
|
||||||
|
|
||||||
|
@ -467,7 +472,7 @@ def kconfig(args: PmbArgs):
|
||||||
if args.package:
|
if args.package:
|
||||||
pkgname = args.package if isinstance(args.package, str) else args.package[0]
|
pkgname = args.package if isinstance(args.package, str) else args.package[0]
|
||||||
else:
|
else:
|
||||||
pkgname = args.deviceinfo["codename"]
|
pkgname = get_context().config.device
|
||||||
use_oldconfig = args.action_kconfig == "migrate"
|
use_oldconfig = args.action_kconfig == "migrate"
|
||||||
pmb.build.menuconfig(args, pkgname, use_oldconfig)
|
pmb.build.menuconfig(args, pkgname, use_oldconfig)
|
||||||
|
|
||||||
|
@ -577,7 +582,7 @@ def zap(args: PmbArgs):
|
||||||
|
|
||||||
|
|
||||||
def bootimg_analyze(args: PmbArgs):
|
def bootimg_analyze(args: PmbArgs):
|
||||||
bootimg = pmb.parse.bootimg(args, args.path)
|
bootimg = pmb.parse.bootimg(args.path)
|
||||||
tmp_output = "Put these variables in the deviceinfo file of your device:\n"
|
tmp_output = "Put these variables in the deviceinfo file of your device:\n"
|
||||||
for line in pmb.aportgen.device.\
|
for line in pmb.aportgen.device.\
|
||||||
generate_deviceinfo_fastboot_content(bootimg).split("\n"):
|
generate_deviceinfo_fastboot_content(bootimg).split("\n"):
|
||||||
|
@ -667,4 +672,4 @@ def ci(args: PmbArgs):
|
||||||
if not scripts_selected:
|
if not scripts_selected:
|
||||||
scripts_selected = pmb.ci.ask_which_scripts_to_run(scripts_available)
|
scripts_selected = pmb.ci.ask_which_scripts_to_run(scripts_available)
|
||||||
|
|
||||||
pmb.ci.run_scripts(args, topdir, scripts_selected)
|
pmb.ci.run_scripts(topdir, scripts_selected)
|
||||||
|
|
|
@ -248,8 +248,11 @@ def get_topdir(repo: Path):
|
||||||
:returns: a string with the top dir of the git repository,
|
:returns: a string with the top dir of the git repository,
|
||||||
or an empty string if it's not a git repository.
|
or an empty string if it's not a git repository.
|
||||||
"""
|
"""
|
||||||
return pmb.helpers.run.user(["git", "rev-parse", "--show-toplevel"],
|
res = pmb.helpers.run.user(["git", "rev-parse", "--show-toplevel"],
|
||||||
repo, output_return=True, check=False).rstrip()
|
repo, output_return=True, check=False)
|
||||||
|
if not isinstance(res, str):
|
||||||
|
raise RuntimeError("Not a git repository: " + str(repo))
|
||||||
|
return res.strip()
|
||||||
|
|
||||||
|
|
||||||
def get_files(repo: Path):
|
def get_files(repo: Path):
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Copyright 2023 Danct12 <danct12@disroot.org>
|
# Copyright 2023 Danct12 <danct12@disroot.org>
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from pmb.core.chroot import Chroot
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
@ -17,12 +18,13 @@ def check(args: PmbArgs, pkgnames):
|
||||||
|
|
||||||
:param pkgnames: Names of the packages to lint
|
:param pkgnames: Names of the packages to lint
|
||||||
"""
|
"""
|
||||||
pmb.chroot.apk.install(["atools"])
|
chroot = Chroot.native()
|
||||||
|
pmb.chroot.apk.install(["atools"], chroot)
|
||||||
|
|
||||||
# Mount pmaports.git inside the chroot so that we don't have to copy the
|
# Mount pmaports.git inside the chroot so that we don't have to copy the
|
||||||
# package folders
|
# package folders
|
||||||
pmaports = Path("/mnt/pmaports")
|
pmaports = Path("/mnt/pmaports")
|
||||||
pmb.build.mount_pmaports(args, pmaports)
|
pmb.build.mount_pmaports(pmaports, chroot)
|
||||||
|
|
||||||
# Locate all APKBUILDs and make the paths be relative to the pmaports
|
# Locate all APKBUILDs and make the paths be relative to the pmaports
|
||||||
# root
|
# root
|
||||||
|
|
|
@ -10,7 +10,9 @@ See also:
|
||||||
"""
|
"""
|
||||||
import copy
|
import copy
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
from pmb.core.context import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
|
import pmb.build._package
|
||||||
|
|
||||||
from pmb.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
|
@ -62,7 +64,7 @@ def get(pkgname, arch, replace_subpkgnames=False, must_exist=True):
|
||||||
pmaport = pmb.helpers.pmaports.get(pkgname, False)
|
pmaport = pmb.helpers.pmaports.get(pkgname, False)
|
||||||
if pmaport:
|
if pmaport:
|
||||||
ret = {"arch": pmaport["arch"],
|
ret = {"arch": pmaport["arch"],
|
||||||
"depends": pmb.build._package.get_depends(args, pmaport),
|
"depends": pmb.build._package.get_depends(get_context(), pmaport),
|
||||||
"pkgname": pmaport["pkgname"],
|
"pkgname": pmaport["pkgname"],
|
||||||
"provides": pmaport["provides"],
|
"provides": pmaport["provides"],
|
||||||
"version": pmaport["pkgver"] + "-r" + pmaport["pkgrel"]}
|
"version": pmaport["pkgver"] + "-r" + pmaport["pkgrel"]}
|
||||||
|
|
|
@ -91,7 +91,7 @@ def auto_apkindex_package(args: PmbArgs, arch, aport, apk, dry=False):
|
||||||
# (which means dynamic libraries that the package was linked
|
# (which means dynamic libraries that the package was linked
|
||||||
# against) and packages for which no aport exists.
|
# against) and packages for which no aport exists.
|
||||||
if (depend.startswith("so:") or
|
if (depend.startswith("so:") or
|
||||||
not pmb.helpers.pmaports.find_optional(args, depend)):
|
not pmb.helpers.pmaports.find_optional(depend)):
|
||||||
missing.append(depend)
|
missing.append(depend)
|
||||||
|
|
||||||
# Increase pkgrel
|
# Increase pkgrel
|
||||||
|
@ -116,7 +116,7 @@ def auto(args: PmbArgs, dry=False):
|
||||||
logging.verbose(
|
logging.verbose(
|
||||||
f"{pkgname}: origin '{origin}' found again")
|
f"{pkgname}: origin '{origin}' found again")
|
||||||
continue
|
continue
|
||||||
aport_path = pmb.helpers.pmaports.find_optional(args, origin)
|
aport_path = pmb.helpers.pmaports.find_optional(origin)
|
||||||
if not aport_path:
|
if not aport_path:
|
||||||
logging.warning("{}: origin '{}' aport not found".format(
|
logging.warning("{}: origin '{}' aport not found".format(
|
||||||
pkgname, origin))
|
pkgname, origin))
|
||||||
|
|
|
@ -58,6 +58,7 @@ def urls(user_repository=True, postmarketos_mirror=True, alpine=True):
|
||||||
"http://...", ...]
|
"http://...", ...]
|
||||||
"""
|
"""
|
||||||
ret: List[str] = []
|
ret: List[str] = []
|
||||||
|
context = get_context()
|
||||||
|
|
||||||
# Get mirrordirs from channels.cfg (postmarketOS mirrordir is the same as
|
# Get mirrordirs from channels.cfg (postmarketOS mirrordir is the same as
|
||||||
# the pmaports branch of the channel, no need to make it more complicated)
|
# the pmaports branch of the channel, no need to make it more complicated)
|
||||||
|
@ -68,9 +69,9 @@ def urls(user_repository=True, postmarketos_mirror=True, alpine=True):
|
||||||
# Local user repository (for packages compiled with pmbootstrap)
|
# Local user repository (for packages compiled with pmbootstrap)
|
||||||
if user_repository:
|
if user_repository:
|
||||||
channel = pmb.config.pmaports.read_config()["channel"]
|
channel = pmb.config.pmaports.read_config()["channel"]
|
||||||
ret.append(str(get_context().config.work / "packages" / channel))
|
# FIXME: We shouldn't hardcod this here
|
||||||
|
ret.append("/mnt/pmbootstrap/packages")
|
||||||
|
|
||||||
context = get_context()
|
|
||||||
# Upstream postmarketOS binary repository
|
# Upstream postmarketOS binary repository
|
||||||
if postmarketos_mirror:
|
if postmarketos_mirror:
|
||||||
for mirror in context.config.mirrors_postmarketos:
|
for mirror in context.config.mirrors_postmarketos:
|
||||||
|
|
|
@ -20,7 +20,7 @@ def get_arch(args: PmbArgs):
|
||||||
return args.arch
|
return args.arch
|
||||||
|
|
||||||
if args.build_default_device_arch:
|
if args.build_default_device_arch:
|
||||||
return args.deviceinfo["arch"]
|
return pmb.parse.deviceinfo()["arch"]
|
||||||
|
|
||||||
return pmb.config.arch_native
|
return pmb.config.arch_native
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ def run_steps(args: PmbArgs, steps, arch, chroot: Chroot):
|
||||||
for package in get_packages(bootstrap_line):
|
for package in get_packages(bootstrap_line):
|
||||||
log_progress(f"building {package}")
|
log_progress(f"building {package}")
|
||||||
bootstrap_stage = int(step.split("bootstrap_", 1)[1])
|
bootstrap_stage = int(step.split("bootstrap_", 1)[1])
|
||||||
pmb.build.package(args, package, arch, force=True,
|
pmb.build.package(package, arch, force=True,
|
||||||
strict=True, bootstrap_stage=bootstrap_stage)
|
strict=True, bootstrap_stage=bootstrap_stage)
|
||||||
|
|
||||||
log_progress("bootstrap complete!")
|
log_progress("bootstrap complete!")
|
||||||
|
@ -175,7 +175,7 @@ def require_bootstrap_error(repo, arch, trigger_str):
|
||||||
" and then try again.")
|
" and then try again.")
|
||||||
|
|
||||||
|
|
||||||
def require_bootstrap(args: PmbArgs, arch, trigger_str):
|
def require_bootstrap(arch, trigger_str):
|
||||||
"""
|
"""
|
||||||
Check if repo_bootstrap was done, if any is needed.
|
Check if repo_bootstrap was done, if any is needed.
|
||||||
|
|
||||||
|
|
|
@ -33,12 +33,12 @@ def print_channel(config: Config) -> None:
|
||||||
print_status_line("Channel", value)
|
print_status_line("Channel", value)
|
||||||
|
|
||||||
|
|
||||||
def print_device(args: PmbArgs, config: Config) -> None:
|
def print_device(config: Config) -> None:
|
||||||
kernel = ""
|
kernel = ""
|
||||||
if pmb.parse._apkbuild.kernels(config.device):
|
if pmb.parse._apkbuild.kernels(config.device):
|
||||||
kernel = f", kernel: {config.kernel}"
|
kernel = f", kernel: {config.kernel}"
|
||||||
|
|
||||||
value = f"{config.device} ({args.deviceinfo['arch']}{kernel})"
|
value = f"{config.device} ({pmb.parse.deviceinfo()['arch']}{kernel})"
|
||||||
print_status_line("Device", value)
|
print_status_line("Device", value)
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,6 +56,6 @@ def print_status(args: PmbArgs) -> None:
|
||||||
:returns: True if all checks passed, False otherwise """
|
:returns: True if all checks passed, False otherwise """
|
||||||
config = get_context().config
|
config = get_context().config
|
||||||
print_channel(config)
|
print_channel(config)
|
||||||
print_device(args, config)
|
print_device(config)
|
||||||
print_ui(config)
|
print_ui(config)
|
||||||
print_systemd(config)
|
print_systemd(config)
|
||||||
|
|
|
@ -9,7 +9,7 @@ import pmb.helpers.package
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
|
|
||||||
|
|
||||||
def list_ui(args: PmbArgs, arch):
|
def list_ui(arch):
|
||||||
"""Get all UIs, for which aports are available with their description.
|
"""Get all UIs, for which aports are available with their description.
|
||||||
|
|
||||||
:param arch: device architecture, for which the UIs must be available
|
:param arch: device architecture, for which the UIs must be available
|
||||||
|
@ -22,7 +22,7 @@ def list_ui(args: PmbArgs, arch):
|
||||||
for path in sorted(context.config.aports.glob("main/postmarketos-ui-*")):
|
for path in sorted(context.config.aports.glob("main/postmarketos-ui-*")):
|
||||||
apkbuild = pmb.parse.apkbuild(path)
|
apkbuild = pmb.parse.apkbuild(path)
|
||||||
ui = os.path.basename(path).split("-", 2)[2]
|
ui = os.path.basename(path).split("-", 2)[2]
|
||||||
if pmb.helpers.package.check_arch(args, apkbuild["pkgname"], arch):
|
if pmb.helpers.package.check_arch(apkbuild["pkgname"], arch):
|
||||||
ret.append((ui, apkbuild["pkgdesc"]))
|
ret.append((ui, apkbuild["pkgdesc"]))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import pmb.helpers.devices
|
||||||
from pmb.helpers.mount import mount_device_rootfs
|
from pmb.helpers.mount import mount_device_rootfs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.helpers.other
|
import pmb.helpers.other
|
||||||
|
import pmb.helpers.package
|
||||||
import pmb.install.blockdevice
|
import pmb.install.blockdevice
|
||||||
import pmb.install.recovery
|
import pmb.install.recovery
|
||||||
import pmb.install.ui
|
import pmb.install.ui
|
||||||
|
@ -113,11 +114,11 @@ def copy_files_from_chroot(args: PmbArgs, chroot: Chroot):
|
||||||
"""
|
"""
|
||||||
# Mount the device rootfs
|
# Mount the device rootfs
|
||||||
logging.info(f"(native) copy {chroot} to /mnt/install/")
|
logging.info(f"(native) copy {chroot} to /mnt/install/")
|
||||||
mountpoint = mount_device_rootfs(args, chroot)
|
mountpoint = mount_device_rootfs(chroot)
|
||||||
mountpoint_outside = Chroot.native() / mountpoint
|
mountpoint_outside = Chroot.native() / mountpoint
|
||||||
|
|
||||||
# Remove empty qemu-user binary stub (where the binary was bind-mounted)
|
# Remove empty qemu-user binary stub (where the binary was bind-mounted)
|
||||||
arch_qemu = pmb.parse.arch.alpine_to_qemu(args.deviceinfo["arch"])
|
arch_qemu = pmb.parse.arch.alpine_to_qemu(pmb.parse.deviceinfo()["arch"])
|
||||||
qemu_binary = mountpoint_outside / ("/usr/bin/qemu-" + arch_qemu + "-static")
|
qemu_binary = mountpoint_outside / ("/usr/bin/qemu-" + arch_qemu + "-static")
|
||||||
if os.path.exists(qemu_binary):
|
if os.path.exists(qemu_binary):
|
||||||
pmb.helpers.run.root(["rm", qemu_binary])
|
pmb.helpers.run.root(["rm", qemu_binary])
|
||||||
|
@ -148,16 +149,16 @@ def copy_files_from_chroot(args: PmbArgs, chroot: Chroot):
|
||||||
working_dir=mountpoint)
|
working_dir=mountpoint)
|
||||||
|
|
||||||
|
|
||||||
def create_home_from_skel(args: PmbArgs):
|
def create_home_from_skel(filesystem: str, user: str):
|
||||||
"""
|
"""
|
||||||
Create /home/{user} from /etc/skel
|
Create /home/{user} from /etc/skel
|
||||||
"""
|
"""
|
||||||
rootfs = (Chroot.native() / "mnt/install")
|
rootfs = (Chroot.native() / "mnt/install")
|
||||||
# In btrfs, home subvol & home dir is created in format.py
|
# In btrfs, home subvol & home dir is created in format.py
|
||||||
if args.filesystem != "btrfs":
|
if filesystem != "btrfs":
|
||||||
pmb.helpers.run.root(["mkdir", rootfs / "home"])
|
pmb.helpers.run.root(["mkdir", rootfs / "home"])
|
||||||
|
|
||||||
home = (rootfs / "home" / args.user)
|
home = (rootfs / "home" / user)
|
||||||
if (rootfs / "etc/skel").exists():
|
if (rootfs / "etc/skel").exists():
|
||||||
pmb.helpers.run.root(["cp", "-a", (rootfs / "etc/skel"), home])
|
pmb.helpers.run.root(["cp", "-a", (rootfs / "etc/skel"), home])
|
||||||
else:
|
else:
|
||||||
|
@ -184,8 +185,7 @@ def configure_apk(args: PmbArgs):
|
||||||
pmb.helpers.run.root(["cp", key, rootfs / "etc/apk/keys/"])
|
pmb.helpers.run.root(["cp", key, rootfs / "etc/apk/keys/"])
|
||||||
|
|
||||||
# Copy over the corresponding APKINDEX files from cache
|
# Copy over the corresponding APKINDEX files from cache
|
||||||
index_files = pmb.helpers.repo.apkindex_files(args,
|
index_files = pmb.helpers.repo.apkindex_files(arch=pmb.parse.deviceinfo()["arch"],
|
||||||
arch=args.deviceinfo["arch"],
|
|
||||||
user_repository=False)
|
user_repository=False)
|
||||||
for f in index_files:
|
for f in index_files:
|
||||||
pmb.helpers.run.root(["cp", f, rootfs / "var/cache/apk/"])
|
pmb.helpers.run.root(["cp", f, rootfs / "var/cache/apk/"])
|
||||||
|
@ -221,7 +221,7 @@ def set_user(config: Config):
|
||||||
pmb.chroot.root(["addgroup", config.user, group], chroot)
|
pmb.chroot.root(["addgroup", config.user, group], chroot)
|
||||||
|
|
||||||
|
|
||||||
def setup_login_chpasswd_user_from_arg(args: PmbArgs, chroot: Chroot):
|
def setup_login_chpasswd_user_from_arg(args: PmbArgs, user: str, chroot: Chroot):
|
||||||
"""
|
"""
|
||||||
Set the user's password from what the user passed as --password. Make an
|
Set the user's password from what the user passed as --password. Make an
|
||||||
effort to not have the password end up in the log file by writing it to
|
effort to not have the password end up in the log file by writing it to
|
||||||
|
@ -237,7 +237,7 @@ def setup_login_chpasswd_user_from_arg(args: PmbArgs, chroot: Chroot):
|
||||||
path_outside = chroot / path
|
path_outside = chroot / path
|
||||||
|
|
||||||
with open(path_outside, "w", encoding="utf-8") as handle:
|
with open(path_outside, "w", encoding="utf-8") as handle:
|
||||||
handle.write(f"{args.user}:{args.password}")
|
handle.write(f"{user}:{args.password}")
|
||||||
|
|
||||||
pmb.chroot.root(["sh", "-c", f"cat {shlex.quote(path)} | chpasswd"],
|
pmb.chroot.root(["sh", "-c", f"cat {shlex.quote(path)} | chpasswd"],
|
||||||
chroot)
|
chroot)
|
||||||
|
@ -258,7 +258,7 @@ def is_root_locked(chroot: Chroot):
|
||||||
return shadow_root.startswith("root:!:")
|
return shadow_root.startswith("root:!:")
|
||||||
|
|
||||||
|
|
||||||
def setup_login(args: PmbArgs, chroot: Chroot):
|
def setup_login(args: PmbArgs, config: Config, chroot: Chroot):
|
||||||
"""
|
"""
|
||||||
Loop until the password for user has been set successfully, and disable
|
Loop until the password for user has been set successfully, and disable
|
||||||
root login.
|
root login.
|
||||||
|
@ -268,13 +268,13 @@ def setup_login(args: PmbArgs, chroot: Chroot):
|
||||||
"""
|
"""
|
||||||
if not args.on_device_installer:
|
if not args.on_device_installer:
|
||||||
# User password
|
# User password
|
||||||
logging.info(f" *** SET LOGIN PASSWORD FOR: '{args.user}' ***")
|
logging.info(f" *** SET LOGIN PASSWORD FOR: '{config.user}' ***")
|
||||||
if args.password:
|
if args.password:
|
||||||
setup_login_chpasswd_user_from_arg(args, chroot)
|
setup_login_chpasswd_user_from_arg(args, config.user, chroot)
|
||||||
else:
|
else:
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
pmb.chroot.root(["passwd", args.user], chroot,
|
pmb.chroot.root(["passwd", config.user], chroot,
|
||||||
output="interactive")
|
output="interactive")
|
||||||
break
|
break
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
|
@ -363,11 +363,9 @@ def setup_keymap(config: Config):
|
||||||
logging.info("NOTE: No valid keymap specified for device")
|
logging.info("NOTE: No valid keymap specified for device")
|
||||||
|
|
||||||
|
|
||||||
def setup_timezone(config: Config):
|
def setup_timezone(chroot: Chroot, timezone: str):
|
||||||
suffix = Chroot(ChrootType.ROOTFS, config.device)
|
# We don't care about the arch since it's built for all!
|
||||||
|
alpine_conf = pmb.helpers.package.get("alpine-conf", pmb.config.arch_native)
|
||||||
arch = args.deviceinfo["arch"]
|
|
||||||
alpine_conf = pmb.helpers.package.get(args, "alpine-conf", arch)
|
|
||||||
version = alpine_conf["version"].split("-r")[0]
|
version = alpine_conf["version"].split("-r")[0]
|
||||||
|
|
||||||
setup_tz_cmd = ["setup-timezone"]
|
setup_tz_cmd = ["setup-timezone"]
|
||||||
|
@ -375,23 +373,22 @@ def setup_timezone(config: Config):
|
||||||
# and disregard tzdata, to save space. If we actually have tzdata
|
# and disregard tzdata, to save space. If we actually have tzdata
|
||||||
# installed, make sure that setup-timezone makes use of it, since
|
# installed, make sure that setup-timezone makes use of it, since
|
||||||
# there's no space to be saved.
|
# there's no space to be saved.
|
||||||
if "tzdata" in pmb.chroot.apk.installed(args, suffix):
|
if "tzdata" in pmb.chroot.apk.installed(chroot):
|
||||||
setup_tz_cmd += ["-i"]
|
setup_tz_cmd += ["-i"]
|
||||||
if not pmb.parse.version.check_string(version, ">=3.14.0"):
|
if not pmb.parse.version.check_string(version, ">=3.14.0"):
|
||||||
setup_tz_cmd += ["-z"]
|
setup_tz_cmd += ["-z"]
|
||||||
setup_tz_cmd += [args.timezone]
|
setup_tz_cmd += [timezone]
|
||||||
pmb.chroot.root(setup_tz_cmd, suffix)
|
pmb.chroot.root(setup_tz_cmd, chroot)
|
||||||
|
|
||||||
|
|
||||||
def setup_hostname(args: PmbArgs):
|
def setup_hostname(device: str, hostname: Optional[str]):
|
||||||
"""
|
"""
|
||||||
Set the hostname and update localhost address in /etc/hosts
|
Set the hostname and update localhost address in /etc/hosts
|
||||||
"""
|
"""
|
||||||
# Default to device name. If device name is not a valid hostname then
|
# Default to device name. If device name is not a valid hostname then
|
||||||
# default to a static default.
|
# default to a static default.
|
||||||
hostname = args.hostname
|
|
||||||
if not hostname:
|
if not hostname:
|
||||||
hostname = args.devicesdhbfvhubsud
|
hostname = device
|
||||||
if not pmb.helpers.other.validate_hostname(hostname):
|
if not pmb.helpers.other.validate_hostname(hostname):
|
||||||
# A valid host name, see:
|
# A valid host name, see:
|
||||||
# https://datatracker.ietf.org/doc/html/rfc1035#section-2.3.1
|
# https://datatracker.ietf.org/doc/html/rfc1035#section-2.3.1
|
||||||
|
@ -402,7 +399,7 @@ def setup_hostname(args: PmbArgs):
|
||||||
raise RuntimeError("Hostname '" + hostname + "' is not valid, please"
|
raise RuntimeError("Hostname '" + hostname + "' is not valid, please"
|
||||||
" run 'pmbootstrap init' to configure it.")
|
" run 'pmbootstrap init' to configure it.")
|
||||||
|
|
||||||
suffix = Chroot(ChrootType.ROOTFS, args.devicesdhbfvhubsud)
|
suffix = Chroot(ChrootType.ROOTFS, device)
|
||||||
# Generate /etc/hostname
|
# Generate /etc/hostname
|
||||||
pmb.chroot.root(["sh", "-c", "echo " + shlex.quote(hostname) +
|
pmb.chroot.root(["sh", "-c", "echo " + shlex.quote(hostname) +
|
||||||
" > /etc/hostname"], suffix)
|
" > /etc/hostname"], suffix)
|
||||||
|
@ -412,37 +409,32 @@ def setup_hostname(args: PmbArgs):
|
||||||
pmb.chroot.root(["sed", "-i", "-e", regex, "/etc/hosts"], suffix)
|
pmb.chroot.root(["sed", "-i", "-e", regex, "/etc/hosts"], suffix)
|
||||||
|
|
||||||
|
|
||||||
def setup_appstream(args: PmbArgs):
|
def setup_appstream(offline: bool, chroot: Chroot):
|
||||||
"""
|
"""
|
||||||
If alpine-appstream-downloader has been downloaded, execute it to have
|
If alpine-appstream-downloader has been downloaded, execute it to have
|
||||||
update AppStream data on new installs
|
update AppStream data on new installs
|
||||||
"""
|
"""
|
||||||
suffix = Chroot(ChrootType.ROOTFS, args.devicesdhbfvhubsud)
|
installed_pkgs = pmb.chroot.apk.installed(chroot)
|
||||||
installed_pkgs = pmb.chroot.apk.installed(args, suffix)
|
|
||||||
|
|
||||||
if "alpine-appstream-downloader" not in installed_pkgs or args.offline:
|
if "alpine-appstream-downloader" not in installed_pkgs or offline:
|
||||||
return
|
return
|
||||||
|
|
||||||
if not pmb.chroot.root(["alpine-appstream-downloader",
|
if not pmb.chroot.root(["alpine-appstream-downloader",
|
||||||
"/mnt/appstream-data"], suffix, check=False):
|
"/mnt/appstream-data"], chroot, check=False):
|
||||||
pmb.chroot.root(["mkdir", "-p", "/var/lib/swcatalog"], suffix)
|
pmb.chroot.root(["mkdir", "-p", "/var/lib/swcatalog"], chroot)
|
||||||
pmb.chroot.root(["cp", "-r", "/mnt/appstream-data/icons",
|
pmb.chroot.root(["cp", "-r", "/mnt/appstream-data/icons",
|
||||||
"/mnt/appstream-data/xml",
|
"/mnt/appstream-data/xml",
|
||||||
"-t", "/var/lib/swcatalog"], suffix)
|
"-t", "/var/lib/swcatalog"], chroot)
|
||||||
|
|
||||||
|
|
||||||
def disable_sshd(args: PmbArgs):
|
def disable_sshd(chroot: Chroot):
|
||||||
if not args.no_sshd:
|
|
||||||
return
|
|
||||||
|
|
||||||
# check=False: rc-update doesn't exit with 0 if already disabled
|
# check=False: rc-update doesn't exit with 0 if already disabled
|
||||||
chroot = Chroot(ChrootType.ROOTFS, args.devicesdhbfvhubsud)
|
|
||||||
pmb.chroot.root(["rc-update", "del", "sshd", "default"], chroot,
|
pmb.chroot.root(["rc-update", "del", "sshd", "default"], chroot,
|
||||||
check=False)
|
check=False)
|
||||||
|
|
||||||
# Verify that it's gone
|
# Verify that it's gone
|
||||||
sshd_files = pmb.helpers.run.root(
|
sshd_files = pmb.helpers.run.root(
|
||||||
args, ["find", "-name", "sshd"], output_return=True,
|
["find", "-name", "sshd"], output_return=True,
|
||||||
working_dir=chroot / "etc/runlevels")
|
working_dir=chroot / "etc/runlevels")
|
||||||
if sshd_files:
|
if sshd_files:
|
||||||
raise RuntimeError(f"Failed to disable sshd service: {sshd_files}")
|
raise RuntimeError(f"Failed to disable sshd service: {sshd_files}")
|
||||||
|
@ -457,7 +449,7 @@ def print_sshd_info(args: PmbArgs):
|
||||||
logging.info("SSH daemon is disabled (--no-sshd).")
|
logging.info("SSH daemon is disabled (--no-sshd).")
|
||||||
else:
|
else:
|
||||||
logging.info("SSH daemon is enabled (disable with --no-sshd).")
|
logging.info("SSH daemon is enabled (disable with --no-sshd).")
|
||||||
logging.info(f"Login as '{args.user}' with the password given"
|
logging.info(f"Login as '{get_context().config.user}' with the password given"
|
||||||
" during installation.")
|
" during installation.")
|
||||||
|
|
||||||
if args.on_device_installer:
|
if args.on_device_installer:
|
||||||
|
@ -469,24 +461,20 @@ def print_sshd_info(args: PmbArgs):
|
||||||
logging.info("More info: https://postmarketos.org/ondev-debug")
|
logging.info("More info: https://postmarketos.org/ondev-debug")
|
||||||
|
|
||||||
|
|
||||||
def disable_firewall(args: PmbArgs):
|
def disable_firewall(chroot: Chroot):
|
||||||
if not args.no_firewall:
|
|
||||||
return
|
|
||||||
|
|
||||||
# check=False: rc-update doesn't exit with 0 if already disabled
|
# check=False: rc-update doesn't exit with 0 if already disabled
|
||||||
chroot = Chroot(ChrootType.ROOTFS, args.devicesdhbfvhubsud)
|
|
||||||
pmb.chroot.root(["rc-update", "del", "nftables", "default"], chroot,
|
pmb.chroot.root(["rc-update", "del", "nftables", "default"], chroot,
|
||||||
check=False)
|
check=False)
|
||||||
|
|
||||||
# Verify that it's gone
|
# Verify that it's gone
|
||||||
nftables_files = pmb.helpers.run.root(
|
nftables_files = pmb.helpers.run.root(
|
||||||
args, ["find", "-name", "nftables"], output_return=True,
|
["find", "-name", "nftables"], output_return=True,
|
||||||
working_dir=chroot / "etc/runlevels")
|
working_dir=chroot / "etc/runlevels")
|
||||||
if nftables_files:
|
if nftables_files:
|
||||||
raise RuntimeError(f"Failed to disable firewall: {nftables_files}")
|
raise RuntimeError(f"Failed to disable firewall: {nftables_files}")
|
||||||
|
|
||||||
|
|
||||||
def print_firewall_info(args: PmbArgs):
|
def print_firewall_info(disabled: bool, arch: str):
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config()
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
pmaports_ok = pmaports_cfg.get("supported_firewall", None) == "nftables"
|
pmaports_ok = pmaports_cfg.get("supported_firewall", None) == "nftables"
|
||||||
|
|
||||||
|
@ -494,7 +482,6 @@ def print_firewall_info(args: PmbArgs):
|
||||||
apkbuild_found = False
|
apkbuild_found = False
|
||||||
apkbuild_has_opt = False
|
apkbuild_has_opt = False
|
||||||
|
|
||||||
arch = args.deviceinfo["arch"]
|
|
||||||
kernel = get_kernel_package(get_context().config)
|
kernel = get_kernel_package(get_context().config)
|
||||||
if kernel:
|
if kernel:
|
||||||
kernel_apkbuild = pmb.build._package.get_apkbuild(kernel[0], arch)
|
kernel_apkbuild = pmb.build._package.get_apkbuild(kernel[0], arch)
|
||||||
|
@ -510,7 +497,7 @@ def print_firewall_info(args: PmbArgs):
|
||||||
if not pmaports_ok:
|
if not pmaports_ok:
|
||||||
logging.info("Firewall is not supported in checked out pmaports"
|
logging.info("Firewall is not supported in checked out pmaports"
|
||||||
" branch.")
|
" branch.")
|
||||||
elif args.no_firewall:
|
elif disabled:
|
||||||
logging.info("Firewall is disabled (--no-firewall).")
|
logging.info("Firewall is disabled (--no-firewall).")
|
||||||
elif not apkbuild_found:
|
elif not apkbuild_found:
|
||||||
logging.info("Firewall is enabled, but may not work (couldn't"
|
logging.info("Firewall is enabled, but may not work (couldn't"
|
||||||
|
@ -538,7 +525,7 @@ def generate_binary_list(args: PmbArgs, chroot: Chroot, step):
|
||||||
"""
|
"""
|
||||||
binary_ranges: Dict[int, int] = {}
|
binary_ranges: Dict[int, int] = {}
|
||||||
binary_list = []
|
binary_list = []
|
||||||
binaries = args.deviceinfo["sd_embed_firmware"].split(",")
|
binaries = pmb.parse.deviceinfo()["sd_embed_firmware"].split(",")
|
||||||
|
|
||||||
for binary_offset in binaries:
|
for binary_offset in binaries:
|
||||||
binary, _offset = binary_offset.split(':')
|
binary, _offset = binary_offset.split(':')
|
||||||
|
@ -554,7 +541,7 @@ def generate_binary_list(args: PmbArgs, chroot: Chroot, step):
|
||||||
f"/usr/share/{binary}")
|
f"/usr/share/{binary}")
|
||||||
# Insure that embedding the firmware will not overrun the
|
# Insure that embedding the firmware will not overrun the
|
||||||
# first partition
|
# first partition
|
||||||
boot_part_start = args.deviceinfo["boot_part_start"] or "2048"
|
boot_part_start = pmb.parse.deviceinfo()["boot_part_start"] or "2048"
|
||||||
max_size = (int(boot_part_start) * 512) - (offset * step)
|
max_size = (int(boot_part_start) * 512) - (offset * step)
|
||||||
binary_size = os.path.getsize(binary_path)
|
binary_size = os.path.getsize(binary_path)
|
||||||
if binary_size > max_size:
|
if binary_size > max_size:
|
||||||
|
@ -587,19 +574,19 @@ def embed_firmware(args: PmbArgs, suffix: Chroot):
|
||||||
:param suffix: of the chroot, which holds the firmware files (either the
|
:param suffix: of the chroot, which holds the firmware files (either the
|
||||||
rootfs_{args.device} or installer_{args.device}
|
rootfs_{args.device} or installer_{args.device}
|
||||||
"""
|
"""
|
||||||
if not args.deviceinfo["sd_embed_firmware"]:
|
if not pmb.parse.deviceinfo()["sd_embed_firmware"]:
|
||||||
return
|
return
|
||||||
|
|
||||||
step = 1024
|
step = 1024
|
||||||
if args.deviceinfo["sd_embed_firmware_step_size"]:
|
if pmb.parse.deviceinfo()["sd_embed_firmware_step_size"]:
|
||||||
try:
|
try:
|
||||||
step = int(args.deviceinfo["sd_embed_firmware_step_size"])
|
step = int(pmb.parse.deviceinfo()["sd_embed_firmware_step_size"])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise RuntimeError("Value for "
|
raise RuntimeError("Value for "
|
||||||
"deviceinfo_sd_embed_firmware_step_size "
|
"deviceinfo_sd_embed_firmware_step_size "
|
||||||
"is not valid: {}".format(step))
|
"is not valid: {}".format(step))
|
||||||
|
|
||||||
device_rootfs = mount_device_rootfs(args, suffix)
|
device_rootfs = mount_device_rootfs(suffix)
|
||||||
binary_list = generate_binary_list(args, suffix, step)
|
binary_list = generate_binary_list(args, suffix, step)
|
||||||
|
|
||||||
# Write binaries to disk
|
# Write binaries to disk
|
||||||
|
@ -619,13 +606,13 @@ def write_cgpt_kpart(args: PmbArgs, layout, suffix: Chroot):
|
||||||
:param layout: partition layout from get_partition_layout()
|
:param layout: partition layout from get_partition_layout()
|
||||||
:param suffix: of the chroot, which holds the image file to be flashed
|
:param suffix: of the chroot, which holds the image file to be flashed
|
||||||
"""
|
"""
|
||||||
if not args.deviceinfo["cgpt_kpart"] or not args.install_cgpt:
|
if not pmb.parse.deviceinfo()["cgpt_kpart"] or not args.install_cgpt:
|
||||||
return
|
return
|
||||||
|
|
||||||
device_rootfs = mount_device_rootfs(args, suffix)
|
device_rootfs = mount_device_rootfs(suffix)
|
||||||
filename = f"{device_rootfs}{args.deviceinfo['cgpt_kpart']}"
|
filename = f"{device_rootfs}{pmb.parse.deviceinfo()['cgpt_kpart']}"
|
||||||
pmb.chroot.root(
|
pmb.chroot.root(
|
||||||
args, ["dd", f"if={filename}", f"of=/dev/installp{layout['kernel']}"])
|
["dd", f"if={filename}", f"of=/dev/installp{layout['kernel']}"])
|
||||||
|
|
||||||
|
|
||||||
def sanity_check_boot_size():
|
def sanity_check_boot_size():
|
||||||
|
@ -680,7 +667,7 @@ def sanity_check_disk_size(args: PmbArgs):
|
||||||
|
|
||||||
|
|
||||||
def get_ondev_pkgver(args: PmbArgs):
|
def get_ondev_pkgver(args: PmbArgs):
|
||||||
arch = args.deviceinfo["arch"]
|
arch = pmb.parse.deviceinfo()["arch"]
|
||||||
package = pmb.helpers.package.get(args, "postmarketos-ondev", arch)
|
package = pmb.helpers.package.get(args, "postmarketos-ondev", arch)
|
||||||
return package["version"].split("-r")[0]
|
return package["version"].split("-r")[0]
|
||||||
|
|
||||||
|
@ -775,7 +762,7 @@ def create_fstab(args: PmbArgs, layout, chroot: Chroot):
|
||||||
else f"UUID={get_uuid(args, root_dev)}"
|
else f"UUID={get_uuid(args, root_dev)}"
|
||||||
|
|
||||||
boot_options = "nodev,nosuid,noexec"
|
boot_options = "nodev,nosuid,noexec"
|
||||||
boot_filesystem = args.deviceinfo["boot_filesystem"] or "ext2"
|
boot_filesystem = pmb.parse.deviceinfo()["boot_filesystem"] or "ext2"
|
||||||
if boot_filesystem in ("fat16", "fat32"):
|
if boot_filesystem in ("fat16", "fat32"):
|
||||||
boot_filesystem = "vfat"
|
boot_filesystem = "vfat"
|
||||||
boot_options += ",umask=0077,nosymfollow,codepage=437,iocharset=ascii"
|
boot_options += ",umask=0077,nosymfollow,codepage=437,iocharset=ascii"
|
||||||
|
@ -821,23 +808,25 @@ def install_system_image(args: PmbArgs, size_reserve, chroot: Chroot, step, step
|
||||||
:param split: create separate images for boot and root partitions
|
:param split: create separate images for boot and root partitions
|
||||||
:param disk: path to disk block device (e.g. /dev/mmcblk0) or None
|
:param disk: path to disk block device (e.g. /dev/mmcblk0) or None
|
||||||
"""
|
"""
|
||||||
|
config = get_context().config
|
||||||
|
device = chroot.name()
|
||||||
# Partition and fill image file/disk block device
|
# Partition and fill image file/disk block device
|
||||||
logging.info(f"*** ({step}/{steps}) PREPARE INSTALL BLOCKDEVICE ***")
|
logging.info(f"*** ({step}/{steps}) PREPARE INSTALL BLOCKDEVICE ***")
|
||||||
pmb.chroot.shutdown(args, True)
|
pmb.chroot.shutdown(args, True)
|
||||||
(size_boot, size_root) = get_subpartitions_size(chroot)
|
(size_boot, size_root) = get_subpartitions_size(chroot)
|
||||||
layout = get_partition_layout(size_reserve, args.deviceinfo["cgpt_kpart"] \
|
layout = get_partition_layout(size_reserve, pmb.parse.deviceinfo()["cgpt_kpart"] \
|
||||||
and args.install_cgpt)
|
and args.install_cgpt)
|
||||||
if not args.rsync:
|
if not args.rsync:
|
||||||
pmb.install.blockdevice.create(args, size_boot, size_root,
|
pmb.install.blockdevice.create(args, size_boot, size_root,
|
||||||
size_reserve, split, disk)
|
size_reserve, split, disk)
|
||||||
if not split:
|
if not split:
|
||||||
if args.deviceinfo["cgpt_kpart"] and args.install_cgpt:
|
if pmb.parse.deviceinfo()["cgpt_kpart"] and args.install_cgpt:
|
||||||
pmb.install.partition_cgpt(
|
pmb.install.partition_cgpt(
|
||||||
args, layout, size_boot, size_reserve)
|
args, layout, size_boot, size_reserve)
|
||||||
else:
|
else:
|
||||||
pmb.install.partition(args, layout, size_boot, size_reserve)
|
pmb.install.partition(args, layout, size_boot, size_reserve)
|
||||||
if not split:
|
if not split:
|
||||||
pmb.install.partitions_mount(args, layout, disk)
|
pmb.install.partitions_mount(device, layout, disk)
|
||||||
|
|
||||||
pmb.install.format(args, layout, boot_label, root_label, disk)
|
pmb.install.format(args, layout, boot_label, root_label, disk)
|
||||||
|
|
||||||
|
@ -860,9 +849,9 @@ def install_system_image(args: PmbArgs, size_reserve, chroot: Chroot, step, step
|
||||||
# Just copy all the files
|
# Just copy all the files
|
||||||
logging.info(f"*** ({step + 1}/{steps}) FILL INSTALL BLOCKDEVICE ***")
|
logging.info(f"*** ({step + 1}/{steps}) FILL INSTALL BLOCKDEVICE ***")
|
||||||
copy_files_from_chroot(args, chroot)
|
copy_files_from_chroot(args, chroot)
|
||||||
create_home_from_skel(args)
|
create_home_from_skel(args.filesystem, config.user)
|
||||||
configure_apk(args)
|
configure_apk(args)
|
||||||
copy_ssh_keys(args)
|
copy_ssh_keys(config)
|
||||||
|
|
||||||
# Don't try to embed firmware and cgpt on split images since there's no
|
# Don't try to embed firmware and cgpt on split images since there's no
|
||||||
# place to put it and it will end up in /dev of the chroot instead
|
# place to put it and it will end up in /dev of the chroot instead
|
||||||
|
@ -878,26 +867,26 @@ def install_system_image(args: PmbArgs, size_reserve, chroot: Chroot, step, step
|
||||||
# Convert rootfs to sparse using img2simg
|
# Convert rootfs to sparse using img2simg
|
||||||
sparse = args.sparse
|
sparse = args.sparse
|
||||||
if sparse is None:
|
if sparse is None:
|
||||||
sparse = args.deviceinfo["flash_sparse"] == "true"
|
sparse = pmb.parse.deviceinfo()["flash_sparse"] == "true"
|
||||||
|
|
||||||
if sparse and not split and not disk:
|
if sparse and not split and not disk:
|
||||||
workdir = Path("/home/pmos/rootfs")
|
workdir = Path("/home/pmos/rootfs")
|
||||||
logging.info("(native) make sparse rootfs")
|
logging.info("(native) make sparse rootfs")
|
||||||
pmb.chroot.apk.install(["android-tools"], Chroot.native())
|
pmb.chroot.apk.install(["android-tools"], Chroot.native())
|
||||||
sys_image = args.devicesdhbfvhubsud + ".img"
|
sys_image = device + ".img"
|
||||||
sys_image_sparse = args.devicesdhbfvhubsud + "-sparse.img"
|
sys_image_sparse = device + "-sparse.img"
|
||||||
pmb.chroot.user(["img2simg", sys_image, sys_image_sparse],
|
pmb.chroot.user(["img2simg", sys_image, sys_image_sparse],
|
||||||
working_dir=workdir)
|
working_dir=workdir)
|
||||||
pmb.chroot.user(["mv", "-f", sys_image_sparse, sys_image],
|
pmb.chroot.user(["mv", "-f", sys_image_sparse, sys_image],
|
||||||
working_dir=workdir)
|
working_dir=workdir)
|
||||||
|
|
||||||
# patch sparse image for Samsung devices if specified
|
# patch sparse image for Samsung devices if specified
|
||||||
samsungify_strategy = args.deviceinfo["flash_sparse_samsung_format"]
|
samsungify_strategy = pmb.parse.deviceinfo()["flash_sparse_samsung_format"]
|
||||||
if samsungify_strategy:
|
if samsungify_strategy:
|
||||||
logging.info("(native) convert sparse image into Samsung's sparse image format")
|
logging.info("(native) convert sparse image into Samsung's sparse image format")
|
||||||
pmb.chroot.apk.install(["sm-sparse-image-tool"], Chroot.native())
|
pmb.chroot.apk.install(["sm-sparse-image-tool"], Chroot.native())
|
||||||
sys_image = f"{args.devicesdhbfvhubsud}.img"
|
sys_image = f"{device}.img"
|
||||||
sys_image_patched = f"{args.devicesdhbfvhubsud}-patched.img"
|
sys_image_patched = f"{device}-patched.img"
|
||||||
pmb.chroot.user(["sm_sparse_image_tool", "samsungify", "--strategy",
|
pmb.chroot.user(["sm_sparse_image_tool", "samsungify", "--strategy",
|
||||||
samsungify_strategy, sys_image, sys_image_patched],
|
samsungify_strategy, sys_image, sys_image_patched],
|
||||||
working_dir=workdir)
|
working_dir=workdir)
|
||||||
|
@ -905,14 +894,14 @@ def install_system_image(args: PmbArgs, size_reserve, chroot: Chroot, step, step
|
||||||
working_dir=workdir)
|
working_dir=workdir)
|
||||||
|
|
||||||
|
|
||||||
def print_flash_info(args: PmbArgs):
|
def print_flash_info(device: str, deviceinfo: Dict[str, str], split: bool, have_disk: bool):
|
||||||
""" Print flashing information, based on the deviceinfo data and the
|
""" Print flashing information, based on the deviceinfo data and the
|
||||||
pmbootstrap arguments. """
|
pmbootstrap arguments. """
|
||||||
logging.info("") # make the note stand out
|
logging.info("") # make the note stand out
|
||||||
logging.info("*** FLASHING INFORMATION ***")
|
logging.info("*** FLASHING INFORMATION ***")
|
||||||
|
|
||||||
# System flash information
|
# System flash information
|
||||||
method = args.deviceinfo["flash_method"]
|
method = deviceinfo["flash_method"]
|
||||||
flasher = pmb.config.flashers.get(method, {})
|
flasher = pmb.config.flashers.get(method, {})
|
||||||
flasher_actions = flasher.get("actions", {})
|
flasher_actions = flasher.get("actions", {})
|
||||||
if not isinstance(flasher_actions, dict):
|
if not isinstance(flasher_actions, dict):
|
||||||
|
@ -929,14 +918,14 @@ def print_flash_info(args: PmbArgs):
|
||||||
logging.info("Run the following to flash your installation to the"
|
logging.info("Run the following to flash your installation to the"
|
||||||
" target device:")
|
" target device:")
|
||||||
|
|
||||||
if "flash_rootfs" in flasher_actions and not args.disk and \
|
if "flash_rootfs" in flasher_actions and not have_disk and \
|
||||||
bool(args.split) == requires_split:
|
bool(split) == requires_split:
|
||||||
logging.info("* pmbootstrap flasher flash_rootfs")
|
logging.info("* pmbootstrap flasher flash_rootfs")
|
||||||
logging.info(" Flashes the generated rootfs image to your device:")
|
logging.info(" Flashes the generated rootfs image to your device:")
|
||||||
if args.split:
|
if split:
|
||||||
logging.info(f" {Chroot.native() / 'home/pmos/rootfs' / args.devicesdhbfvhubsud}-rootfs.img")
|
logging.info(f" {Chroot.native() / 'home/pmos/rootfs' / device}-rootfs.img")
|
||||||
else:
|
else:
|
||||||
logging.info(f" {Chroot.native() / 'home/pmos/rootfs' / args.devicesdhbfvhubsud}.img")
|
logging.info(f" {Chroot.native() / 'home/pmos/rootfs' / device}.img")
|
||||||
logging.info(" (NOTE: This file has a partition table, which"
|
logging.info(" (NOTE: This file has a partition table, which"
|
||||||
" contains /boot and / subpartitions. That way we"
|
" contains /boot and / subpartitions. That way we"
|
||||||
" don't need to change the partition layout on your"
|
" don't need to change the partition layout on your"
|
||||||
|
@ -945,16 +934,16 @@ def print_flash_info(args: PmbArgs):
|
||||||
# if current flasher supports vbmeta and partition is explicitly specified
|
# if current flasher supports vbmeta and partition is explicitly specified
|
||||||
# in deviceinfo
|
# in deviceinfo
|
||||||
if "flash_vbmeta" in flasher_actions and \
|
if "flash_vbmeta" in flasher_actions and \
|
||||||
(args.deviceinfo["flash_fastboot_partition_vbmeta"] or
|
(deviceinfo["flash_fastboot_partition_vbmeta"] or
|
||||||
args.deviceinfo["flash_heimdall_partition_vbmeta"]):
|
deviceinfo["flash_heimdall_partition_vbmeta"]):
|
||||||
logging.info("* pmbootstrap flasher flash_vbmeta")
|
logging.info("* pmbootstrap flasher flash_vbmeta")
|
||||||
logging.info(" Flashes vbmeta image with verification disabled flag.")
|
logging.info(" Flashes vbmeta image with verification disabled flag.")
|
||||||
|
|
||||||
# if current flasher supports dtbo and partition is explicitly specified
|
# if current flasher supports dtbo and partition is explicitly specified
|
||||||
# in deviceinfo
|
# in deviceinfo
|
||||||
if "flash_dtbo" in flasher_actions and \
|
if "flash_dtbo" in flasher_actions and \
|
||||||
(args.deviceinfo["flash_fastboot_partition_dtbo"] or
|
(deviceinfo["flash_fastboot_partition_dtbo"] or
|
||||||
args.deviceinfo["flash_heimdall_partition_dtbo"]):
|
deviceinfo["flash_heimdall_partition_dtbo"]):
|
||||||
logging.info("* pmbootstrap flasher flash_dtbo")
|
logging.info("* pmbootstrap flasher flash_dtbo")
|
||||||
logging.info(" Flashes dtbo image.")
|
logging.info(" Flashes dtbo image.")
|
||||||
|
|
||||||
|
@ -963,14 +952,14 @@ def print_flash_info(args: PmbArgs):
|
||||||
# works even when partitions are split or installing to disk. This is not
|
# works even when partitions are split or installing to disk. This is not
|
||||||
# possible if the flash method requires split partitions.
|
# possible if the flash method requires split partitions.
|
||||||
if "flash_kernel" in flasher_actions and \
|
if "flash_kernel" in flasher_actions and \
|
||||||
(not requires_split or args.split):
|
(not requires_split or split):
|
||||||
logging.info("* pmbootstrap flasher flash_kernel")
|
logging.info("* pmbootstrap flasher flash_kernel")
|
||||||
logging.info(" Flashes the kernel + initramfs to your device:")
|
logging.info(" Flashes the kernel + initramfs to your device:")
|
||||||
if requires_split:
|
if requires_split:
|
||||||
logging.info(f" {Chroot.native()}/home/pmos/rootfs/"
|
logging.info(f" {Chroot.native()}/home/pmos/rootfs/"
|
||||||
f"{args.devicesdhbfvhubsud}-boot.img")
|
f"{device}-boot.img")
|
||||||
else:
|
else:
|
||||||
logging.info(f" {Chroot(ChrootType.ROOTFS, args.devicesdhbfvhubsud)}/boot")
|
logging.info(f" {Chroot(ChrootType.ROOTFS, device)}/boot")
|
||||||
|
|
||||||
if "boot" in flasher_actions:
|
if "boot" in flasher_actions:
|
||||||
logging.info(" (NOTE: " + method + " also supports booting"
|
logging.info(" (NOTE: " + method + " also supports booting"
|
||||||
|
@ -978,7 +967,7 @@ def print_flash_info(args: PmbArgs):
|
||||||
" Use 'pmbootstrap flasher boot' to do that.)")
|
" Use 'pmbootstrap flasher boot' to do that.)")
|
||||||
|
|
||||||
if "flash_lk2nd" in flasher_actions and \
|
if "flash_lk2nd" in flasher_actions and \
|
||||||
(Chroot(ChrootType.ROOTFS, args.devicesdhbfvhubsud) / "/boot/lk2nd.img").exists():
|
(Chroot(ChrootType.ROOTFS, device) / "/boot/lk2nd.img").exists():
|
||||||
logging.info("* Your device supports and may even require"
|
logging.info("* Your device supports and may even require"
|
||||||
" flashing lk2nd. You should flash it before"
|
" flashing lk2nd. You should flash it before"
|
||||||
" flashing anything else. Use 'pmbootstrap flasher"
|
" flashing anything else. Use 'pmbootstrap flasher"
|
||||||
|
@ -990,11 +979,11 @@ def print_flash_info(args: PmbArgs):
|
||||||
" and flash outside of pmbootstrap.")
|
" and flash outside of pmbootstrap.")
|
||||||
|
|
||||||
|
|
||||||
def install_recovery_zip(args: PmbArgs, steps):
|
def install_recovery_zip(args: PmbArgs, device: str, arch: str, steps):
|
||||||
logging.info(f"*** ({steps}/{steps}) CREATING RECOVERY-FLASHABLE ZIP ***")
|
logging.info(f"*** ({steps}/{steps}) CREATING RECOVERY-FLASHABLE ZIP ***")
|
||||||
suffix = "buildroot_" + args.deviceinfo["arch"]
|
chroot = Chroot(ChrootType.BUILDROOT, arch)
|
||||||
mount_device_rootfs(args, Chroot.rootfs(args.devicesdhbfvhubsud))
|
mount_device_rootfs(Chroot.rootfs(device))
|
||||||
pmb.install.recovery.create_zip(args, suffix)
|
pmb.install.recovery.create_zip(args, chroot, device)
|
||||||
|
|
||||||
# Flash information
|
# Flash information
|
||||||
logging.info("*** FLASHING INFORMATION ***")
|
logging.info("*** FLASHING INFORMATION ***")
|
||||||
|
@ -1060,12 +1049,12 @@ def install_on_device_installer(args: PmbArgs, step, steps):
|
||||||
# Remove $DEVICE-boot.img (we will generate a new one if --split was
|
# Remove $DEVICE-boot.img (we will generate a new one if --split was
|
||||||
# specified, otherwise the separate boot image is not needed)
|
# specified, otherwise the separate boot image is not needed)
|
||||||
if not args.ondev_no_rootfs:
|
if not args.ondev_no_rootfs:
|
||||||
img_boot = f"{args.devicesdhbfvhubsud}-boot.img"
|
img_boot = f"{config.device}-boot.img"
|
||||||
logging.info(f"(native) rm {img_boot}")
|
logging.info(f"(native) rm {img_boot}")
|
||||||
pmb.chroot.root(["rm", f"/home/pmos/rootfs/{img_boot}"])
|
pmb.chroot.root(["rm", f"/home/pmos/rootfs/{img_boot}"])
|
||||||
|
|
||||||
# Disable root login
|
# Disable root login
|
||||||
setup_login(args, chroot_installer)
|
setup_login(args, config, chroot_installer)
|
||||||
|
|
||||||
# Generate installer image
|
# Generate installer image
|
||||||
size_reserve = round(os.path.getsize(img_path_dest) / 1024 / 1024) + 200
|
size_reserve = round(os.path.getsize(img_path_dest) / 1024 / 1024) + 200
|
||||||
|
@ -1185,8 +1174,8 @@ def create_device_rootfs(args: PmbArgs, step, steps):
|
||||||
logging.info(f'*** ({step}/{steps}) CREATE DEVICE ROOTFS ("{device}")'
|
logging.info(f'*** ({step}/{steps}) CREATE DEVICE ROOTFS ("{device}")'
|
||||||
' ***')
|
' ***')
|
||||||
|
|
||||||
suffix = Chroot(ChrootType.ROOTFS, device)
|
chroot = Chroot(ChrootType.ROOTFS, device)
|
||||||
pmb.chroot.init(suffix)
|
pmb.chroot.init(chroot)
|
||||||
# Create user before installing packages, so post-install scripts of
|
# Create user before installing packages, so post-install scripts of
|
||||||
# pmaports can figure out the username (legacy reasons: pmaports#820)
|
# pmaports can figure out the username (legacy reasons: pmaports#820)
|
||||||
set_user(context.config)
|
set_user(context.config)
|
||||||
|
@ -1215,7 +1204,7 @@ def create_device_rootfs(args: PmbArgs, step, steps):
|
||||||
install_packages += context.config.extra_packages.split(",")
|
install_packages += context.config.extra_packages.split(",")
|
||||||
if args.add:
|
if args.add:
|
||||||
install_packages += args.add.split(",")
|
install_packages += args.add.split(",")
|
||||||
locale_is_set = (config.locale != pmb.config.defaults["locale"])
|
locale_is_set = (config.locale != Config().locale)
|
||||||
if locale_is_set:
|
if locale_is_set:
|
||||||
install_packages += ["lang", "musl-locales"]
|
install_packages += ["lang", "musl-locales"]
|
||||||
|
|
||||||
|
@ -1231,58 +1220,63 @@ def create_device_rootfs(args: PmbArgs, step, steps):
|
||||||
# Pick the most suitable unlocker depending on the packages
|
# Pick the most suitable unlocker depending on the packages
|
||||||
# selected for installation
|
# selected for installation
|
||||||
unlocker = pmb.parse.depends.package_provider(
|
unlocker = pmb.parse.depends.package_provider(
|
||||||
"postmarketos-fde-unlocker", install_packages, suffix)
|
"postmarketos-fde-unlocker", install_packages, chroot)
|
||||||
if unlocker["pkgname"] not in install_packages:
|
if unlocker["pkgname"] not in install_packages:
|
||||||
install_packages += [unlocker["pkgname"]]
|
install_packages += [unlocker["pkgname"]]
|
||||||
else:
|
else:
|
||||||
install_packages += ["postmarketos-base-nofde"]
|
install_packages += ["postmarketos-base-nofde"]
|
||||||
|
|
||||||
pmb.helpers.repo.update(args.deviceinfo["arch"])
|
pmb.helpers.repo.update(pmb.parse.deviceinfo()["arch"])
|
||||||
|
|
||||||
# Install uninstallable "dependencies" by default
|
# Install uninstallable "dependencies" by default
|
||||||
install_packages += get_recommends(args, install_packages)
|
install_packages += get_recommends(args, install_packages)
|
||||||
|
|
||||||
# Explicitly call build on the install packages, to re-build them or any
|
# Explicitly call build on the install packages, to re-build them or any
|
||||||
# dependency, in case the version increased
|
# dependency, in case the version increased
|
||||||
if args.build_pkgs_on_install:
|
if config.build_pkgs_on_install:
|
||||||
for pkgname in install_packages:
|
for pkgname in install_packages:
|
||||||
pmb.build.package(context, pkgname, args.deviceinfo["arch"])
|
pmb.build.package(context, pkgname, pmb.parse.deviceinfo()["arch"])
|
||||||
|
|
||||||
# Install all packages to device rootfs chroot (and rebuild the initramfs,
|
# Install all packages to device rootfs chroot (and rebuild the initramfs,
|
||||||
# because that doesn't always happen automatically yet, e.g. when the user
|
# because that doesn't always happen automatically yet, e.g. when the user
|
||||||
# installed a hook without pmbootstrap - see #69 for more info)
|
# installed a hook without pmbootstrap - see #69 for more info)
|
||||||
pmb.chroot.apk.install(install_packages, suffix)
|
pmb.chroot.apk.install(install_packages, chroot)
|
||||||
flavor = pmb.chroot.other.kernel_flavor_installed(suffix)
|
flavor = pmb.chroot.other.kernel_flavor_installed(chroot)
|
||||||
pmb.chroot.initfs.build(args, flavor, suffix)
|
pmb.chroot.initfs.build(flavor, chroot)
|
||||||
|
|
||||||
# Set the user password
|
# Set the user password
|
||||||
setup_login(args, suffix)
|
setup_login(args, config, chroot)
|
||||||
|
|
||||||
# Set the keymap if the device requires it
|
# Set the keymap if the device requires it
|
||||||
setup_keymap(config)
|
setup_keymap(config)
|
||||||
|
|
||||||
# Set timezone
|
# Set timezone
|
||||||
setup_timezone(config)
|
setup_timezone(chroot, config.timezone)
|
||||||
|
|
||||||
# Set locale
|
# Set locale
|
||||||
if locale_is_set:
|
if locale_is_set:
|
||||||
# 10locale-pmos.sh gets sourced before 20locale.sh from
|
# 10locale-pmos.sh gets sourced before 20locale.sh from
|
||||||
# alpine-baselayout by /etc/profile. Since they don't override the
|
# alpine-baselayout by /etc/profile. Since they don't override the
|
||||||
# locale if it exists, it warranties we have preference
|
# locale if it exists, it warranties we have preference
|
||||||
line = f"export LANG=${{LANG:-{shlex.quote(args.locale)}}}"
|
line = f"export LANG=${{LANG:-{shlex.quote(config.locale)}}}"
|
||||||
pmb.chroot.root(["sh", "-c", f"echo {shlex.quote(line)}"
|
pmb.chroot.root(["sh", "-c", f"echo {shlex.quote(line)}"
|
||||||
" > /etc/profile.d/10locale-pmos.sh"], suffix)
|
" > /etc/profile.d/10locale-pmos.sh"], chroot)
|
||||||
|
|
||||||
# Set the hostname as the device name
|
# Set the hostname as the device name
|
||||||
setup_hostname(args)
|
setup_hostname(device, config.hostname)
|
||||||
|
|
||||||
setup_appstream(args)
|
setup_appstream(context.offline, chroot)
|
||||||
|
|
||||||
disable_sshd(args)
|
if args.no_sshd:
|
||||||
disable_firewall(args)
|
disable_sshd(chroot)
|
||||||
|
if args.no_firewall:
|
||||||
|
disable_firewall(chroot)
|
||||||
|
|
||||||
|
|
||||||
def install(args: PmbArgs):
|
def install(args: PmbArgs):
|
||||||
|
device = get_context().config.device
|
||||||
|
chroot = Chroot(ChrootType.ROOTFS, device)
|
||||||
|
deviceinfo = pmb.parse.deviceinfo()
|
||||||
# Sanity checks
|
# Sanity checks
|
||||||
sanity_check_boot_size()
|
sanity_check_boot_size()
|
||||||
if not args.android_recovery_zip and args.disk:
|
if not args.android_recovery_zip and args.disk:
|
||||||
|
@ -1319,18 +1313,18 @@ def install(args: PmbArgs):
|
||||||
if args.no_image:
|
if args.no_image:
|
||||||
return
|
return
|
||||||
elif args.android_recovery_zip:
|
elif args.android_recovery_zip:
|
||||||
return install_recovery_zip(args, steps)
|
return install_recovery_zip(args, device, deviceinfo["arch"], steps)
|
||||||
|
|
||||||
if args.on_device_installer:
|
if args.on_device_installer:
|
||||||
# Runs install_system_image twice
|
# Runs install_system_image twice
|
||||||
install_on_device_installer(args, step, steps)
|
install_on_device_installer(args, step, steps)
|
||||||
else:
|
else:
|
||||||
install_system_image(args, 0, Chroot(ChrootType.ROOTFS, args.devicesdhbfvhubsud), step, steps,
|
install_system_image(args, 0, chroot, step, steps,
|
||||||
split=args.split, disk=args.disk)
|
split=args.split, disk=args.disk)
|
||||||
|
|
||||||
print_flash_info(args)
|
print_flash_info(device, deviceinfo, args.split, True if args.disk and args.disk.is_absolute() else False)
|
||||||
print_sshd_info(args)
|
print_sshd_info(args)
|
||||||
print_firewall_info(args)
|
print_firewall_info(args.no_firewall, deviceinfo["arch"])
|
||||||
|
|
||||||
# Leave space before 'chroot still active' note
|
# Leave space before 'chroot still active' note
|
||||||
logging.info("")
|
logging.info("")
|
||||||
|
|
|
@ -23,7 +23,7 @@ def format_and_mount_boot(args: PmbArgs, device, boot_label):
|
||||||
ondev-prepare-internal-storage.sh in postmarketos-ondev.git!
|
ondev-prepare-internal-storage.sh in postmarketos-ondev.git!
|
||||||
"""
|
"""
|
||||||
mountpoint = "/mnt/install/boot"
|
mountpoint = "/mnt/install/boot"
|
||||||
filesystem = args.deviceinfo["boot_filesystem"] or "ext2"
|
filesystem = pmb.parse.deviceinfo()["boot_filesystem"] or "ext2"
|
||||||
install_fsprogs(filesystem)
|
install_fsprogs(filesystem)
|
||||||
logging.info(f"(native) format {device} (boot, {filesystem}), mount to"
|
logging.info(f"(native) format {device} (boot, {filesystem}), mount to"
|
||||||
f" {mountpoint}")
|
f" {mountpoint}")
|
||||||
|
@ -72,7 +72,7 @@ def format_luks_root(args: PmbArgs, device):
|
||||||
|
|
||||||
|
|
||||||
def get_root_filesystem(args: PmbArgs):
|
def get_root_filesystem(args: PmbArgs):
|
||||||
ret = args.filesystem or args.deviceinfo["root_filesystem"] or "ext4"
|
ret = args.filesystem or pmb.parse.deviceinfo()["root_filesystem"] or "ext4"
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config()
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
|
|
||||||
supported = pmaports_cfg.get("supported_root_filesystems", "ext4")
|
supported = pmaports_cfg.get("supported_root_filesystems", "ext4")
|
||||||
|
|
|
@ -42,7 +42,7 @@ def mount(args: PmbArgs, img_path: Path):
|
||||||
init()
|
init()
|
||||||
|
|
||||||
losetup_cmd: List[PathString] = ["losetup", "-f", img_path]
|
losetup_cmd: List[PathString] = ["losetup", "-f", img_path]
|
||||||
sector_size = args.deviceinfo["rootfs_image_sector_size"]
|
sector_size = pmb.parse.deviceinfo()["rootfs_image_sector_size"]
|
||||||
if sector_size:
|
if sector_size:
|
||||||
losetup_cmd += ["-b", str(int(sector_size))]
|
losetup_cmd += ["-b", str(int(sector_size))]
|
||||||
|
|
||||||
|
|
|
@ -14,15 +14,15 @@ from pmb.core import Chroot
|
||||||
|
|
||||||
# FIXME (#2324): this function drops disk to a string because it's easier
|
# FIXME (#2324): this function drops disk to a string because it's easier
|
||||||
# to manipulate, this is probably bad.
|
# to manipulate, this is probably bad.
|
||||||
def partitions_mount(args: PmbArgs, layout, disk: Optional[Path]):
|
def partitions_mount(device: str, layout, disk: Optional[Path]):
|
||||||
"""
|
"""
|
||||||
Mount blockdevices of partitions inside native chroot
|
Mount blockdevices of partitions inside native chroot
|
||||||
:param layout: partition layout from get_partition_layout()
|
:param layout: partition layout from get_partition_layout()
|
||||||
:param disk: path to disk block device (e.g. /dev/mmcblk0) or None
|
:param disk: path to disk block device (e.g. /dev/mmcblk0) or None
|
||||||
"""
|
"""
|
||||||
if not disk:
|
if not disk:
|
||||||
img_path = Path("/home/pmos/rootfs") / f"{args.devicesdhbfvhubsud}.img"
|
img_path = Path("/home/pmos/rootfs") / f"{device}.img"
|
||||||
disk = pmb.install.losetup.device_by_back_file(args, img_path)
|
disk = pmb.install.losetup.device_by_back_file(img_path)
|
||||||
|
|
||||||
logging.info(f"Mounting partitions of {disk} inside the chroot")
|
logging.info(f"Mounting partitions of {disk} inside the chroot")
|
||||||
|
|
||||||
|
@ -80,15 +80,15 @@ def partition(args: PmbArgs, layout, size_boot, size_reserve):
|
||||||
logging.info(f"(native) partition /dev/install (boot: {mb_boot},"
|
logging.info(f"(native) partition /dev/install (boot: {mb_boot},"
|
||||||
f" reserved: {mb_reserved}, root: the rest)")
|
f" reserved: {mb_reserved}, root: the rest)")
|
||||||
|
|
||||||
filesystem = args.deviceinfo["boot_filesystem"] or "ext2"
|
filesystem = pmb.parse.deviceinfo()["boot_filesystem"] or "ext2"
|
||||||
|
|
||||||
# Actual partitioning with 'parted'. Using check=False, because parted
|
# Actual partitioning with 'parted'. Using check=False, because parted
|
||||||
# sometimes "fails to inform the kernel". In case it really failed with
|
# sometimes "fails to inform the kernel". In case it really failed with
|
||||||
# partitioning, the follow-up mounting/formatting will not work, so it
|
# partitioning, the follow-up mounting/formatting will not work, so it
|
||||||
# will stop there (see #463).
|
# will stop there (see #463).
|
||||||
boot_part_start = args.deviceinfo["boot_part_start"] or "2048"
|
boot_part_start = pmb.parse.deviceinfo()["boot_part_start"] or "2048"
|
||||||
|
|
||||||
partition_type = args.deviceinfo["partition_type"] or "msdos"
|
partition_type = pmb.parse.deviceinfo()["partition_type"] or "msdos"
|
||||||
|
|
||||||
commands = [
|
commands = [
|
||||||
["mktable", partition_type],
|
["mktable", partition_type],
|
||||||
|
@ -128,11 +128,11 @@ def partition_cgpt(args: PmbArgs, layout, size_boot, size_reserve):
|
||||||
:param size_reserve: empty partition between root and boot in MiB (pma#463)
|
:param size_reserve: empty partition between root and boot in MiB (pma#463)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pmb.chroot.apk.install(["cgpt"], build=False)
|
pmb.chroot.apk.install(["cgpt"], Chroot.native(), build=False)
|
||||||
|
|
||||||
cgpt = {
|
cgpt = {
|
||||||
'kpart_start': args.deviceinfo["cgpt_kpart_start"],
|
'kpart_start': pmb.parse.deviceinfo()["cgpt_kpart_start"],
|
||||||
'kpart_size': args.deviceinfo["cgpt_kpart_size"],
|
'kpart_size': pmb.parse.deviceinfo()["cgpt_kpart_size"],
|
||||||
}
|
}
|
||||||
|
|
||||||
# Convert to MB and print info
|
# Convert to MB and print info
|
||||||
|
@ -178,7 +178,7 @@ def partition_cgpt(args: PmbArgs, layout, size_boot, size_reserve):
|
||||||
]
|
]
|
||||||
|
|
||||||
dev_size = pmb.chroot.root(
|
dev_size = pmb.chroot.root(
|
||||||
args, ["blockdev", "--getsz", "/dev/install"], output_return=True)
|
["blockdev", "--getsz", "/dev/install"], output_return=True)
|
||||||
# 33: Sec GPT table (32) + Sec GPT header (1)
|
# 33: Sec GPT table (32) + Sec GPT header (1)
|
||||||
root_size = str(int(dev_size) - int(s_root_start) - 33)
|
root_size = str(int(dev_size) - int(s_root_start) - 33)
|
||||||
|
|
||||||
|
|
|
@ -1,38 +1,40 @@
|
||||||
# Copyright 2023 Attila Szollosi
|
# Copyright 2023 Attila Szollosi
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from pmb.core.chroot import Chroot
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
|
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
|
import pmb.chroot.apk
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
from pmb.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.flasher
|
import pmb.flasher
|
||||||
import pmb.helpers.frontend
|
import pmb.helpers.frontend
|
||||||
|
|
||||||
|
|
||||||
def create_zip(args: PmbArgs, suffix):
|
def create_zip(args: PmbArgs, chroot: Chroot, device: str):
|
||||||
"""
|
"""
|
||||||
Create android recovery compatible installer zip.
|
Create android recovery compatible installer zip.
|
||||||
"""
|
"""
|
||||||
zip_root = Path("/var/lib/postmarketos-android-recovery-installer/")
|
zip_root = Path("/var/lib/postmarketos-android-recovery-installer/")
|
||||||
rootfs = "/mnt/rootfs_" + args.devicesdhbfvhubsud
|
rootfs = "/mnt/rootfs_" + device
|
||||||
flavor = pmb.helpers.frontend._parse_flavor(args)
|
flavor = pmb.helpers.frontend._parse_flavor(device)
|
||||||
method = args.deviceinfo["flash_method"]
|
deviceinfo = pmb.parse.deviceinfo()
|
||||||
|
method = deviceinfo["flash_method"]
|
||||||
vars = pmb.flasher.variables(args, flavor, method)
|
vars = pmb.flasher.variables(args, flavor, method)
|
||||||
|
|
||||||
# Install recovery installer package in buildroot
|
# Install recovery installer package in buildroot
|
||||||
pmb.chroot.apk.install(args,
|
pmb.chroot.apk.install(["postmarketos-android-recovery-installer"],
|
||||||
["postmarketos-android-recovery-installer"],
|
chroot)
|
||||||
suffix)
|
|
||||||
|
|
||||||
logging.info(f"({suffix}) create recovery zip")
|
logging.info(f"({chroot}) create recovery zip")
|
||||||
|
|
||||||
for key in vars:
|
for key in vars:
|
||||||
pmb.flasher.check_partition_blacklist(args, key, vars[key])
|
pmb.flasher.check_partition_blacklist(args, deviceinfo, key, vars[key])
|
||||||
|
|
||||||
# Create config file for the recovery installer
|
# Create config file for the recovery installer
|
||||||
options = {
|
options = {
|
||||||
"DEVICE": args.devicesdhbfvhubsud,
|
"DEVICE": device,
|
||||||
"FLASH_KERNEL": args.recovery_flash_kernel,
|
"FLASH_KERNEL": args.recovery_flash_kernel,
|
||||||
"ISOREC": method == "heimdall-isorec",
|
"ISOREC": method == "heimdall-isorec",
|
||||||
"KERNEL_PARTLABEL": vars["$PARTITION_KERNEL"],
|
"KERNEL_PARTLABEL": vars["$PARTITION_KERNEL"],
|
||||||
|
@ -52,7 +54,7 @@ def create_zip(args: PmbArgs, suffix):
|
||||||
options["FLAVOR"] = f"-{flavor}" if flavor is not None else "-"
|
options["FLAVOR"] = f"-{flavor}" if flavor is not None else "-"
|
||||||
|
|
||||||
# Write to a temporary file
|
# Write to a temporary file
|
||||||
config_temp = suffix / "tmp/install_options"
|
config_temp = chroot / "tmp/install_options"
|
||||||
with config_temp.open("w") as handle:
|
with config_temp.open("w") as handle:
|
||||||
for key, value in options.items():
|
for key, value in options.items():
|
||||||
if isinstance(value, bool):
|
if isinstance(value, bool):
|
||||||
|
@ -69,6 +71,6 @@ def create_zip(args: PmbArgs, suffix):
|
||||||
["tar", "-prf", "rootfs.tar", "-C", "/", "./etc/apk/keys"],
|
["tar", "-prf", "rootfs.tar", "-C", "/", "./etc/apk/keys"],
|
||||||
# Compress with -1 for speed improvement
|
# Compress with -1 for speed improvement
|
||||||
["gzip", "-f1", "rootfs.tar"],
|
["gzip", "-f1", "rootfs.tar"],
|
||||||
["build-recovery-zip", args.devicesdhbfvhubsud]]
|
["build-recovery-zip", device]]
|
||||||
for command in commands:
|
for command in commands:
|
||||||
pmb.chroot.root(command, suffix, working_dir=zip_root)
|
pmb.chroot.root(command, chroot, working_dir=zip_root)
|
||||||
|
|
|
@ -1,45 +1,46 @@
|
||||||
# Copyright 2023 Mark Hargreaves, Luca Weiss
|
# Copyright 2023 Mark Hargreaves, Luca Weiss
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
from pmb.core.context import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import socket
|
import socket
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import pmb.chroot.run
|
import pmb.chroot
|
||||||
from pmb.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot
|
||||||
|
|
||||||
|
|
||||||
def start_nbd_server(args: PmbArgs, ip="172.16.42.2", port=9999):
|
def start_nbd_server(device: str, replace: bool, ip="172.16.42.2", port=9999):
|
||||||
"""
|
"""
|
||||||
Start nbd server in chroot_native with pmOS rootfs.
|
Start nbd server in chroot_native with pmOS rootfs.
|
||||||
:param ip: IP address to serve nbd server for
|
:param ip: IP address to serve nbd server for
|
||||||
:param port: port of nbd server
|
:param port: port of nbd server
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pmb.chroot.apk.install(['nbd'])
|
pmb.chroot.apk.install(['nbd'], Chroot.native())
|
||||||
|
|
||||||
chroot = Chroot.native()
|
chroot = Chroot.native()
|
||||||
|
|
||||||
rootfs_path = Path("/mnt/pmbootstrap/netboot") / f"{args.devicesdhbfvhubsud}.img"
|
rootfs_path = Path("/mnt/pmbootstrap/netboot") / f"{device}.img"
|
||||||
if not (chroot / rootfs_path).exists() or args.replace:
|
if not (chroot / rootfs_path).exists() or replace:
|
||||||
rootfs_path2 = Path("/home/pmos/rootfs") / f"{args.devicesdhbfvhubsud}.img"
|
rootfs_path2 = Path("/home/pmos/rootfs") / f"{device}.img"
|
||||||
if not (chroot / rootfs_path2).exists():
|
if not (chroot / rootfs_path2).exists():
|
||||||
raise RuntimeError("The rootfs has not been generated yet, please "
|
raise RuntimeError("The rootfs has not been generated yet, please "
|
||||||
"run 'pmbootstrap install' first.")
|
"run 'pmbootstrap install' first.")
|
||||||
if args.replace and not \
|
if replace and not \
|
||||||
pmb.helpers.cli.confirm(f"Are you sure you want to "
|
pmb.helpers.cli.confirm(f"Are you sure you want to "
|
||||||
f"replace the rootfs for "
|
f"replace the rootfs for "
|
||||||
f"{args.devicesdhbfvhubsud}?"):
|
f"{device}?"):
|
||||||
return
|
return
|
||||||
pmb.chroot.run(args, ["cp", rootfs_path2, rootfs_path])
|
pmb.chroot.root(["cp", rootfs_path2, rootfs_path])
|
||||||
logging.info(f"NOTE: Copied device image to {get_context().config.work}"
|
logging.info(f"NOTE: Copied device image to {get_context().config.work}"
|
||||||
f"/images_netboot/. The image will persist \"pmbootstrap "
|
f"/images_netboot/. The image will persist \"pmbootstrap "
|
||||||
f"zap\" for your convenience. Use \"pmbootstrap netboot "
|
f"zap\" for your convenience. Use \"pmbootstrap netboot "
|
||||||
f"serve --help\" for more options.")
|
f"serve --help\" for more options.")
|
||||||
|
|
||||||
logging.info(f"Running nbd server for {args.devicesdhbfvhubsud} on {ip} port {port}.")
|
logging.info(f"Running nbd server for {device} on {ip} port {port}.")
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
logging.info("Waiting for postmarketOS device to appear...")
|
logging.info("Waiting for postmarketOS device to appear...")
|
||||||
|
@ -61,8 +62,7 @@ def start_nbd_server(args: PmbArgs, ip="172.16.42.2", port=9999):
|
||||||
break
|
break
|
||||||
|
|
||||||
logging.info("Found postmarketOS device, serving image...")
|
logging.info("Found postmarketOS device, serving image...")
|
||||||
pmb.chroot.run(
|
pmb.chroot.root(["nbd-server", f"{ip}@{port}", rootfs_path, "-d"],
|
||||||
args, ["nbd-server", f"{ip}@{port}", rootfs_path, "-d"],
|
|
||||||
check=False, disable_timeout=True)
|
check=False, disable_timeout=True)
|
||||||
logging.info("nbd-server quit. Connection lost?")
|
logging.info("nbd-server quit. Connection lost?")
|
||||||
# On a reboot nbd-server will quit, but the IP address sticks around
|
# On a reboot nbd-server will quit, but the IP address sticks around
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
# mypy: disable-error-code="attr-defined"
|
# mypy: disable-error-code="attr-defined"
|
||||||
|
from pmb.core.context import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
|
@ -594,11 +594,8 @@ def arguments_ci(subparser):
|
||||||
|
|
||||||
|
|
||||||
def package_completer(prefix, action, parser=None, parsed_args=None):
|
def package_completer(prefix, action, parser=None, parsed_args=None):
|
||||||
args = parsed_args
|
|
||||||
pmb.config.merge_with_args(args)
|
|
||||||
pmb.helpers.args.replace_placeholders(args)
|
|
||||||
packages = set(
|
packages = set(
|
||||||
package for package in pmb.helpers.pmaports.get_list(args)
|
package for package in pmb.helpers.pmaports.get_list()
|
||||||
if package.startswith(prefix))
|
if package.startswith(prefix))
|
||||||
return packages
|
return packages
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
import os
|
import os
|
||||||
|
from pmb.core.context import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pmb.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.chroot.run
|
import pmb.chroot
|
||||||
import pmb.chroot.other
|
import pmb.chroot.other
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot
|
||||||
|
@ -72,7 +73,7 @@ def get_qcdt_type(path):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def bootimg(args: PmbArgs, path: Path):
|
def bootimg(path: Path):
|
||||||
if not path.exists():
|
if not path.exists():
|
||||||
raise RuntimeError(f"Could not find file '{path}'")
|
raise RuntimeError(f"Could not find file '{path}'")
|
||||||
|
|
||||||
|
@ -93,7 +94,7 @@ def bootimg(args: PmbArgs, path: Path):
|
||||||
working_dir=temp_path,
|
working_dir=temp_path,
|
||||||
output_return=True).rstrip()
|
output_return=True).rstrip()
|
||||||
if "android bootimg" not in file_output.lower():
|
if "android bootimg" not in file_output.lower():
|
||||||
if "force" in args and args.force:
|
if get_context().force:
|
||||||
logging.warning("WARNING: boot.img file seems to be invalid, but"
|
logging.warning("WARNING: boot.img file seems to be invalid, but"
|
||||||
" proceeding anyway (-f specified)")
|
" proceeding anyway (-f specified)")
|
||||||
else:
|
else:
|
||||||
|
@ -166,6 +167,6 @@ def bootimg(args: PmbArgs, path: Path):
|
||||||
output["cmdline"] = f.read().replace('\n', '')
|
output["cmdline"] = f.read().replace('\n', '')
|
||||||
|
|
||||||
# Cleanup
|
# Cleanup
|
||||||
pmb.chroot.run.user(["rm", "-r", temp_path])
|
pmb.chroot.user(["rm", "-r", temp_path])
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
|
@ -230,7 +230,7 @@ def check_config(config_path, config_arch, pkgver, components_list=[],
|
||||||
return all(results)
|
return all(results)
|
||||||
|
|
||||||
|
|
||||||
def check(args: PmbArgs, pkgname, components_list=[], details=False, must_exist=True):
|
def check(pkgname, components_list=[], details=False, must_exist=True):
|
||||||
"""
|
"""
|
||||||
Check for necessary kernel config options in a package.
|
Check for necessary kernel config options in a package.
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
import subprocess
|
import subprocess
|
||||||
from typing import Sequence
|
from typing import Sequence
|
||||||
|
from pmb.core.context import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
@ -24,12 +25,12 @@ import pmb.parse.cpuinfo
|
||||||
from pmb.core import Chroot, ChrootType
|
from pmb.core import Chroot, ChrootType
|
||||||
|
|
||||||
|
|
||||||
def system_image(args: PmbArgs):
|
def system_image(device: str):
|
||||||
"""
|
"""
|
||||||
Returns path to rootfs for specified device. In case that it doesn't
|
Returns path to rootfs for specified device. In case that it doesn't
|
||||||
exist, raise and exception explaining how to generate it.
|
exist, raise and exception explaining how to generate it.
|
||||||
"""
|
"""
|
||||||
path = Chroot.native() / "home/pmos/rootfs" / f"{args.devicesdhbfvhubsud}.img"
|
path = Chroot.native() / "home/pmos/rootfs" / f"{device}.img"
|
||||||
if not path.exists():
|
if not path.exists():
|
||||||
logging.debug(f"Could not find rootfs: {path}")
|
logging.debug(f"Could not find rootfs: {path}")
|
||||||
raise RuntimeError("The rootfs has not been generated yet, please "
|
raise RuntimeError("The rootfs has not been generated yet, please "
|
||||||
|
@ -37,14 +38,14 @@ def system_image(args: PmbArgs):
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
def create_second_storage(args: PmbArgs):
|
def create_second_storage(args: PmbArgs, device: str):
|
||||||
"""
|
"""
|
||||||
Generate a second storage image if it does not exist.
|
Generate a second storage image if it does not exist.
|
||||||
|
|
||||||
:returns: path to the image or None
|
:returns: path to the image or None
|
||||||
|
|
||||||
"""
|
"""
|
||||||
path = Chroot.native() / "home/pmos/rootfs" / f"{args.devicesdhbfvhubsud}-2nd.img"
|
path = Chroot.native() / "home/pmos/rootfs" / f"{device}-2nd.img"
|
||||||
pmb.helpers.run.root(["touch", path])
|
pmb.helpers.run.root(["touch", path])
|
||||||
pmb.helpers.run.root(["chmod", "a+w", path])
|
pmb.helpers.run.root(["chmod", "a+w", path])
|
||||||
resize_image(args, args.second_storage, path)
|
resize_image(args, args.second_storage, path)
|
||||||
|
@ -87,11 +88,11 @@ def create_gdk_loader_cache(args: PmbArgs) -> Path:
|
||||||
return chroot_native / custom_cache_path
|
return chroot_native / custom_cache_path
|
||||||
|
|
||||||
|
|
||||||
def command_qemu(args: PmbArgs, arch, img_path, img_path_2nd=None):
|
def command_qemu(args: PmbArgs, device: str, arch, img_path, img_path_2nd=None):
|
||||||
"""
|
"""
|
||||||
Generate the full qemu command with arguments to run postmarketOS
|
Generate the full qemu command with arguments to run postmarketOS
|
||||||
"""
|
"""
|
||||||
cmdline = args.deviceinfo["kernel_cmdline"]
|
cmdline = pmb.parse.deviceinfo()["kernel_cmdline"]
|
||||||
if args.cmdline:
|
if args.cmdline:
|
||||||
cmdline = args.cmdline
|
cmdline = args.cmdline
|
||||||
|
|
||||||
|
@ -102,9 +103,9 @@ def command_qemu(args: PmbArgs, arch, img_path, img_path_2nd=None):
|
||||||
|
|
||||||
port_ssh = str(args.port)
|
port_ssh = str(args.port)
|
||||||
|
|
||||||
chroot = Chroot(ChrootType.ROOTFS, args.devicesdhbfvhubsud)
|
chroot = Chroot(ChrootType.ROOTFS, device)
|
||||||
chroot_native = Chroot.native()
|
chroot_native = Chroot.native()
|
||||||
flavor = pmb.chroot.other.kernel_flavor_installed(args, chroot)
|
flavor = pmb.chroot.other.kernel_flavor_installed(chroot)
|
||||||
flavor_suffix = f"-{flavor}"
|
flavor_suffix = f"-{flavor}"
|
||||||
# Backwards compatibility with old mkinitfs (pma#660)
|
# Backwards compatibility with old mkinitfs (pma#660)
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config()
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
|
@ -220,7 +221,7 @@ def command_qemu(args: PmbArgs, arch, img_path, img_path_2nd=None):
|
||||||
"if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF.fd"]
|
"if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF.fd"]
|
||||||
|
|
||||||
# Kernel Virtual Machine (KVM) support
|
# Kernel Virtual Machine (KVM) support
|
||||||
native = pmb.config.arch_native == args.deviceinfo["arch"]
|
native = pmb.config.arch_native == pmb.parse.deviceinfo()["arch"]
|
||||||
if args.qemu_kvm and native and os.path.exists("/dev/kvm"):
|
if args.qemu_kvm and native and os.path.exists("/dev/kvm"):
|
||||||
command += ["-enable-kvm"]
|
command += ["-enable-kvm"]
|
||||||
command += ["-cpu", "host"]
|
command += ["-cpu", "host"]
|
||||||
|
@ -315,7 +316,7 @@ def install_depends(args: PmbArgs, arch):
|
||||||
]
|
]
|
||||||
|
|
||||||
# QEMU packaging isn't split up as much in 3.12
|
# QEMU packaging isn't split up as much in 3.12
|
||||||
channel_cfg = pmb.config.pmaports.read_config_channel(args)
|
channel_cfg = pmb.config.pmaports.read_config_channel()
|
||||||
if channel_cfg["branch_aports"] == "3.12-stable":
|
if channel_cfg["branch_aports"] == "3.12-stable":
|
||||||
depends.remove("qemu-hw-display-virtio-gpu")
|
depends.remove("qemu-hw-display-virtio-gpu")
|
||||||
depends.remove("qemu-hw-display-virtio-gpu-pci")
|
depends.remove("qemu-hw-display-virtio-gpu-pci")
|
||||||
|
@ -332,22 +333,23 @@ def run(args: PmbArgs):
|
||||||
"""
|
"""
|
||||||
Run a postmarketOS image in qemu
|
Run a postmarketOS image in qemu
|
||||||
"""
|
"""
|
||||||
if not args.devicesdhbfvhubsud.startswith("qemu-"):
|
device = get_context().config.device
|
||||||
|
if not device.startswith("qemu-"):
|
||||||
raise RuntimeError("'pmbootstrap qemu' can be only used with one of "
|
raise RuntimeError("'pmbootstrap qemu' can be only used with one of "
|
||||||
"the QEMU device packages. Run 'pmbootstrap init' "
|
"the QEMU device packages. Run 'pmbootstrap init' "
|
||||||
"and select the 'qemu' vendor.")
|
"and select the 'qemu' vendor.")
|
||||||
arch = pmb.parse.arch.alpine_to_qemu(args.deviceinfo["arch"])
|
arch = pmb.parse.arch.alpine_to_qemu(pmb.parse.deviceinfo()["arch"])
|
||||||
|
|
||||||
img_path = system_image(args)
|
img_path = system_image(device)
|
||||||
img_path_2nd = None
|
img_path_2nd = None
|
||||||
if args.second_storage:
|
if args.second_storage:
|
||||||
img_path_2nd = create_second_storage(args)
|
img_path_2nd = create_second_storage(args, device)
|
||||||
|
|
||||||
if not args.host_qemu:
|
if not args.host_qemu:
|
||||||
install_depends(args, arch)
|
install_depends(args, arch)
|
||||||
logging.info("Running postmarketOS in QEMU VM (" + arch + ")")
|
logging.info("Running postmarketOS in QEMU VM (" + arch + ")")
|
||||||
|
|
||||||
qemu, env = command_qemu(args, arch, img_path, img_path_2nd)
|
qemu, env = command_qemu(args, device, arch, img_path, img_path_2nd)
|
||||||
|
|
||||||
# Workaround: QEMU runs as local user and needs write permissions in the
|
# Workaround: QEMU runs as local user and needs write permissions in the
|
||||||
# rootfs, which is owned by root
|
# rootfs, which is owned by root
|
||||||
|
|
11
pmb/types.py
11
pmb/types.py
|
@ -46,7 +46,6 @@ class PmbArgs(Namespace):
|
||||||
autoinstall: str
|
autoinstall: str
|
||||||
boot_size: str
|
boot_size: str
|
||||||
build_default_device_arch: str
|
build_default_device_arch: str
|
||||||
build_pkgs_on_install: bool
|
|
||||||
buildroot: str
|
buildroot: str
|
||||||
built: str
|
built: str
|
||||||
ccache_size: str
|
ccache_size: str
|
||||||
|
@ -72,14 +71,13 @@ class PmbArgs(Namespace):
|
||||||
filesystem: str
|
filesystem: str
|
||||||
flash_method: str
|
flash_method: str
|
||||||
folder: str
|
folder: str
|
||||||
force: str
|
force: bool
|
||||||
fork_alpine: str
|
fork_alpine: str
|
||||||
# This is a filthy lie
|
# This is a filthy lie
|
||||||
from_argparse: "PmbArgs"
|
from_argparse: "PmbArgs"
|
||||||
full_disk_encryption: str
|
full_disk_encryption: str
|
||||||
hook: str
|
hook: str
|
||||||
host: str
|
host: str
|
||||||
hostname: str
|
|
||||||
host_qemu: str
|
host_qemu: str
|
||||||
image_size: str
|
image_size: str
|
||||||
install_base: str
|
install_base: str
|
||||||
|
@ -101,7 +99,7 @@ class PmbArgs(Namespace):
|
||||||
name: str
|
name: str
|
||||||
no_depends: str
|
no_depends: str
|
||||||
no_fde: str
|
no_fde: str
|
||||||
no_firewall: str
|
no_firewall: bool
|
||||||
no_image: str
|
no_image: str
|
||||||
non_existing: str
|
non_existing: str
|
||||||
no_reboot: str
|
no_reboot: str
|
||||||
|
@ -132,7 +130,7 @@ class PmbArgs(Namespace):
|
||||||
recovery_flash_kernel: str
|
recovery_flash_kernel: str
|
||||||
recovery_install_partition: str
|
recovery_install_partition: str
|
||||||
ref: str
|
ref: str
|
||||||
replace: str
|
replace: bool
|
||||||
repository: str
|
repository: str
|
||||||
reset: str
|
reset: str
|
||||||
resume: str
|
resume: str
|
||||||
|
@ -142,7 +140,7 @@ class PmbArgs(Namespace):
|
||||||
second_storage: str
|
second_storage: str
|
||||||
selected_providers: Dict[str, str]
|
selected_providers: Dict[str, str]
|
||||||
sparse: str
|
sparse: str
|
||||||
split: str
|
split: bool
|
||||||
src: str
|
src: str
|
||||||
ssh_keys: str
|
ssh_keys: str
|
||||||
strict: str
|
strict: str
|
||||||
|
@ -150,7 +148,6 @@ class PmbArgs(Namespace):
|
||||||
suffix: str
|
suffix: str
|
||||||
systemd: str
|
systemd: str
|
||||||
timeout: float
|
timeout: float
|
||||||
user: str
|
|
||||||
value: str
|
value: str
|
||||||
verbose: str
|
verbose: str
|
||||||
verify: str
|
verify: str
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue