From ee6c406cb88c9e520f1aca4dc242a9bb89daeca0 Mon Sep 17 00:00:00 2001 From: Guy Sheffer Date: Wed, 16 Oct 2024 00:48:53 +0300 Subject: [PATCH] Support librecomputer Le Potato AML-S905X-CC Debian image --- src/custompios_core/base_image_downloader.py | 76 ++++++++++++++++--- src/images.yml | 10 +++ src/modules/base/start_chroot_script | 13 +++- .../disable-services/start_chroot_script | 2 +- 4 files changed, 89 insertions(+), 12 deletions(-) diff --git a/src/custompios_core/base_image_downloader.py b/src/custompios_core/base_image_downloader.py index a68d08d1..7d8c26de 100755 --- a/src/custompios_core/base_image_downloader.py +++ b/src/custompios_core/base_image_downloader.py @@ -7,10 +7,16 @@ import hashlib import shutil import re +import urllib.parse +from enum import Enum, auto from typing import Dict, Any, Optional, cast, Tuple from common import get_image_config, read_images PRECENT_PROGRESS_SIZE = 5 +class ChecksumType(Enum): + URL = auto() # a url for the checksum file + STRING = auto() # A string in the format "checksum filename" + class ChecksumFailException(Exception): pass @@ -74,12 +80,12 @@ def get_sha256(filename): return file_checksum return -def download_image_http(board: Dict[str, Any], dest_folder: str, redownload: bool = False): +def download_image_http(board: Dict[str, Any], dest_folder: str): url = board["url"] checksum = board["checksum"] - download_http(url, checksum) + download_http(url, checksum, dest_folder) -def download_http(url: str, checksum_url: str, dest_folder: str, redownload: bool = False): +def download_http(url: str, checksum_argument: str, dest_folder: str, checksum_type: ChecksumType = ChecksumType.URL): with tempfile.TemporaryDirectory() as tmpdirname: print('created temporary directory', tmpdirname) temp_file_name = os.path.join(tmpdirname, "image.xz") @@ -89,18 +95,30 @@ def download_http(url: str, checksum_url: str, dest_folder: str, redownload: boo try: # Get sha and confirm its the right image download_progress = DownloadProgress() - _, headers_checksum = urllib.request.urlretrieve(checksum_url, temp_file_checksum, download_progress.show_progress) - file_name_checksum = get_file_name(headers_checksum, checksum_url) - checksum_data = None - with open(temp_file_checksum, 'r') as f: - checksum_data = f.read() + # We need to get the checksum as one of ChecksumType enum, the result goes in to online_checksum + online_checksum = None + if checksum_type == ChecksumType.URL: + print(checksum_type) + exit(1) + _, headers_checksum = urllib.request.urlretrieve(checksum_argument, temp_file_checksum, download_progress.show_progress) + file_name_checksum = get_file_name(headers_checksum, checksum_argument) + + checksum_data = None + with open(temp_file_checksum, 'r') as f: + checksum_data = f.read() - checksum_data_parsed = [x.strip() for x in checksum_data.split()] + checksum_data_parsed = [x.strip() for x in checksum_data.split()] + + elif checksum_type == ChecksumType.STRING: + checksum_data_parsed = checksum_argument.split(" ") + else: + print("Error: provided a non-existant checksum type") + exit(1) online_checksum = checksum_data_parsed[0] file_name_from_checksum = checksum_data_parsed[1] dest_file_name = os.path.join(dest_folder, file_name_from_checksum) - print(f"Downloading {dest_file_name}") + print(f"Downloading {dest_file_name} from {url}") if os.path.isfile(dest_file_name): file_checksum = get_sha256(dest_file_name) @@ -149,6 +167,40 @@ def download_image_rpi(board: Dict[str, Any], dest_folder: str): download_http(download_url, checksum_url, dest_folder) return +def get_checksum_libre_computer(os_name: str, os_version: str, file_name: str) -> Optional[str]: + checksum_url = f"https://computer-libre-distro.us-east-1.linodeobjects.com/ci/{os_name}/{os_version}/SHA256SUMS" + checksum_files_data = download_webpage(checksum_url) + for line in checksum_files_data.splitlines(): + checksum, name = line.split(maxsplit=1) + print(name) + if name == file_name: + return f"{checksum} {file_name}" + return None + + +def download_image_libre_computer(board: Dict[str, Any], dest_folder: str): + # URL example: https://distro.libre.computer/ci/raspbian/12/2023-10-10-raspbian-bookworm-arm64%2Baml-s905x-cc.img.xz + # URL example: https://distro.libre.computer/ci/debian/12/debian-12-base-arm64%2Baml-s905x-cc.img.xz + port = board.get("port", "base") + arch = board.get("arch", "arm64+aml") + distribution = board.get("distribution", "bookworm") + os_name = board.get("os_name", "debian") + os_version = board.get("os_version", "12") + board = "s905x-cc" + + # download_url = f"https://downloads.raspberrypi.org/{os_name}_{port}/images/{os_name}_{port}-{version_folder}/{version_file}-{os_name}-{distribution}-{port}.img.xz" + file_name = None + if os_name == "debian": + file_name = f"{os_name}-{os_version}-{port}-{arch}-{board}.img.xz" + download_url = f"https://distro.libre.computer/ci/{os_name}/{os_version}/{urllib.parse.quote(file_name)}" + + checksum = get_checksum_libre_computer(os_name, os_version, file_name) + if checksum is None: + print(f"Error: Can't find the correct checksum for {file_name}") + exit(1) + + download_http(download_url, checksum, dest_folder, ChecksumType.STRING) + return if __name__ == "__main__": parser = argparse.ArgumentParser(add_help=True, description='Download images based on BASE_BOARD and BASE_O') @@ -171,9 +223,13 @@ def download_image_rpi(board: Dict[str, Any], dest_folder: str): if image_config["type"] == "http": print(f"Downloading image for {base_board}") download_image_http(image_config, base_image_path) + download_image_http(image_config, base_image_path) elif image_config["type"] == "rpi": print(f"Downloading Raspberry Pi image for {base_board}") download_image_rpi(image_config, base_image_path) + elif image_config["type"] == "libre.computer": + print(f"Downloading image for {base_board}") + download_image_libre_computer(image_config, base_image_path) elif image_config["type"] == "torrent": print("Error: Torrent not implemented") exit(1) diff --git a/src/images.yml b/src/images.yml index 78c96ee2..d7eafd1c 100644 --- a/src/images.yml +++ b/src/images.yml @@ -64,3 +64,13 @@ images: BASE_ADD_USER: "yes" BASE_USER: "pi" BASE_USER_PASSWORD: "lepotato" + debian_lepotato: + description: "Le Potato AML-S905X-CC Debian image" + type: libre.computer + env: + BASE_ARCH: arm64 + BASE_DISTRO: debian + BASE_BOOT_MOUNT_PATH: boot/efi + BASE_IMAGE_RASPBIAN: "no" + BASE_USER: "pi" + BASE_USER_PASSWORD: "lepotato" diff --git a/src/modules/base/start_chroot_script b/src/modules/base/start_chroot_script index fa39b8bc..5bdf5f1f 100644 --- a/src/modules/base/start_chroot_script +++ b/src/modules/base/start_chroot_script @@ -142,8 +142,18 @@ then cat /home/"${BASE_USER}"/.pydistutils.cfg fi + +if [ "$BASE_DISTRO" == "debian" ]; then + # This fails if we don't disable password expire, so removing that so we can install avahi-daemon + chage -d $(date +%Y-%m-%d) root +fi + if [ "$BASE_SSH_ENABLE" == "yes" ] then + if [ "$BASE_DISTRO" == "debian" ]; then + apt-get update --allow-releaseinfo-change + apt-get install -y openssh-server + fi touch /"${BASE_BOOT_MOUNT_PATH}"/ssh ### Fix SSH incoming echo "IPQoS 0x00" >> /etc/ssh/sshd_config @@ -159,7 +169,8 @@ then fi # Store version buildbase -echo "$CUSTOM_PI_OS_BUILDBASE" > /etc/custompios_buildbase +# TODO: FIX +# echo "$CUSTOM_PI_OS_BUILDBASE" > /etc/custompios_buildbase # Store dist version echo "$DIST_VERSION" > /etc/${DIST_NAME,,}_version diff --git a/src/modules/disable-services/start_chroot_script b/src/modules/disable-services/start_chroot_script index 659fd0a4..61b051fb 100644 --- a/src/modules/disable-services/start_chroot_script +++ b/src/modules/disable-services/start_chroot_script @@ -11,7 +11,7 @@ install_cleanup_trap apt-get update --allow-releaseinfo-change --allow-releaseinfo-change if [ $( is_in_apt policykit-1 ) -eq 1 ]; then - sudo apt-get -y install policykit-1 + apt-get -y install policykit-1 fi # prevent any installed services from automatically starting