mirror of
https://github.com/rosalinux/image-builder.git
synced 2025-02-23 10:22:50 +00:00
mkosi tools for bootstrapping distro and images
This commit is contained in:
parent
c7fe20c8b3
commit
5c716dd277
34 changed files with 186 additions and 10549 deletions
27
README.md
27
README.md
|
@ -1,27 +0,0 @@
|
|||
# TODO for `image-builder` Project
|
||||
|
||||
1. **Add a handler for `boot.cmd`**
|
||||
- Implement processing and integration of `boot.cmd` during image creation.
|
||||
- Ensure compatibility with common boot scenarios.
|
||||
|
||||
2. **Kernel Build from Custom Configurations**
|
||||
- Develop a mechanism to compile the Linux kernel using custom `.config` files.
|
||||
- Provide clear documentation for users to supply and use their own configurations.
|
||||
|
||||
3. **Custom Kernel Installation (Non-Repository)**
|
||||
- Design a solution for installing custom-built kernels that are not available in standard repositories.
|
||||
- Consider integrating a kernel packaging or direct installation process.
|
||||
|
||||
4. **Enhance U-Boot Writing Functionality**
|
||||
- Finalize the function for writing U-Boot to `/dev/loopX`.
|
||||
- Add error handling, validation, and logging to ensure robustness.
|
||||
|
||||
5. **Finalize Loop Device Unmount Function**
|
||||
- Complete the function to properly unmount `/dev/loop` devices after use.
|
||||
- Implement safeguards to prevent accidental unmounting of active devices.
|
||||
|
||||
6. **Root Password Setup**
|
||||
- Resolve issues with `systemd-firstboot` for setting the root password.
|
||||
- Implement a workaround to delete the default `root` user before initializing a new password.
|
||||
- Alternatively, explore other methods for securely setting the root password during image creation.
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
RELEASE="rosa13"
|
||||
ABF_DOWNLOADS="https://abf-downloads.rosa.ru"
|
||||
PKGS="basesystem systemd openssh-server dnf rosa-repos"
|
||||
WEAK_DEPS="false"
|
||||
DEFAULT_USER="rosa"
|
||||
DEFAULT_USER_PASSWORD="rosa"
|
||||
PASSWD_ROOT="root"
|
91
build.py
91
build.py
|
@ -1,91 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import multiprocessing
|
||||
from utils.bootstrap_setup import setup_bootstrap
|
||||
from utils.common import load_config, clone_repo
|
||||
from utils.make_disk import create_disk_image, setup_loop_device
|
||||
from utils.make_disk import create_partitions, mount_partitions
|
||||
from utils.generate_spec import generate_spec_file
|
||||
from utils.kernel import clone_kernel, make_kernel_tar
|
||||
from utils.uboot import build_uboot, flash_uboot
|
||||
from utils.patch import apply_uboot_patches, apply_kernel_patches
|
||||
from utils.rpmbuild import run_rpmbuild
|
||||
|
||||
|
||||
BASE_DIR = os.getcwd()
|
||||
TMP_DIR = os.path.join(BASE_DIR, "tmp")
|
||||
NUM_CORES = str(multiprocessing.cpu_count())
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 3 or "--distro" not in sys.argv:
|
||||
print("example: python build.py --distro <distro_name> <vendor/device> [--skip-kernel] [--skip-uboot] [--skip-rootfs]")
|
||||
print("""Usage: optional features:
|
||||
--skip-kernel [do not build kernel]
|
||||
--skip-uboot [do not build u-boot]
|
||||
--skip-rootfs [do not create distro rootfs]""")
|
||||
sys.exit(1)
|
||||
|
||||
distro_idx = sys.argv.index("--distro") + 1
|
||||
distro = sys.argv[distro_idx]
|
||||
vendor_device = sys.argv[distro_idx + 1]
|
||||
vendor, device = vendor_device.split("/")
|
||||
config_path = os.path.join("device", vendor, device, "config")
|
||||
skip_kernel = "--skip-kernel" in sys.argv
|
||||
skip_uboot = "--skip-uboot" in sys.argv
|
||||
skip_rootfs = "--skip-rootfs" in sys.argv
|
||||
|
||||
if not os.path.exists(config_path):
|
||||
print(f"Configuration file for {vendor}/{device} not found.")
|
||||
sys.exit(1)
|
||||
|
||||
config = load_config(config_path)
|
||||
arch = config["ARCH"]
|
||||
|
||||
print(f"Building for {vendor}/{device} with distro {distro}...")
|
||||
|
||||
if not skip_kernel:
|
||||
kernel_dir = os.path.join(TMP_DIR, vendor, device, "kernel")
|
||||
clone_kernel(TMP_DIR, BASE_DIR, config, vendor, device, kernel_dir)
|
||||
generate_spec_file(TMP_DIR, config, vendor, device)
|
||||
kernel_rpm_dir = os.path.join(TMP_DIR, vendor, device, "kernel-build")
|
||||
make_kernel_tar(kernel_dir, kernel_rpm_dir)
|
||||
# Call rpmbuild to build the kernel RPM
|
||||
try:
|
||||
run_rpmbuild(kernel_rpm_dir, arch)
|
||||
except Exception as e:
|
||||
print(f"Failed to build RPM: {e}")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("Skipping kernel build.")
|
||||
|
||||
if not skip_uboot:
|
||||
build_uboot(TMP_DIR, BASE_DIR, config, vendor, device)
|
||||
else:
|
||||
print("Skipping U-Boot build.")
|
||||
|
||||
if not skip_rootfs:
|
||||
# dd here
|
||||
disk_image_path = create_disk_image(TMP_DIR, config, vendor, device)
|
||||
if disk_image_path:
|
||||
loop_device = setup_loop_device(disk_image_path)
|
||||
print(f"Loop device setup at {loop_device}")
|
||||
# fdisk, mkfs here
|
||||
create_partitions(loop_device, config)
|
||||
if not skip_uboot:
|
||||
flash_uboot(loop_device, TMP_DIR, config, vendor, device)
|
||||
mount_partitions(config, loop_device, TMP_DIR, vendor, device)
|
||||
# dnf install rootfs here
|
||||
setup_bootstrap("bootstrap", TMP_DIR, vendor, device, distro, arch)
|
||||
|
||||
else:
|
||||
print("Skipping rootfs bootstrap")
|
||||
|
||||
print(f"Build completed for {vendor}/{device} with distro {distro}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,20 +0,0 @@
|
|||
ARCH="aarch64"
|
||||
|
||||
EXTRA_PKGS="kernel-raspberry"
|
||||
#KERNEL="https://github.com/raspberrypi/linux.git#rpi-6.6.y"
|
||||
#KERNEL_CONFIG="bcm2711_defconfig"
|
||||
#KERNEL_EXTRACONFIG="--module NTFS3_FS --enable NTFS3_LZX_XPRESS --enable NTFS3_FS_POSIX_ACL --disable NTFS3_64BIT_CLUSTER"
|
||||
DTB="broadcom/bcm2711-rpi-4-b"
|
||||
|
||||
CMDLINE="dwc_otg.lpm_enable=0 console=ttyS0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait"
|
||||
NEED_INITRD=no
|
||||
|
||||
# disk section
|
||||
# /boot is vfat partition
|
||||
BOOT_FSTYPE="vfat"
|
||||
BOOT_SIZE="256MB"
|
||||
# / is ext4 partition
|
||||
ROOT_FSTYPE="ext4"
|
||||
ROOT_SIZE="1024MB"
|
||||
|
||||
# PRESET_CONFIG="local_config"
|
|
@ -1,25 +0,0 @@
|
|||
# See
|
||||
# https://www.raspberrypi.org/documentation/configuration/config-txt
|
||||
arm_64bit=1
|
||||
kernel=kernel8.img
|
||||
dtoverlay=vc4-kms-v3d-pi4
|
||||
# Force the monitor to HDMI mode so that sound will be sent over HDMI cable
|
||||
hdmi_drive=2
|
||||
# Force monitor mode to DMT
|
||||
hdmi_group=2
|
||||
# Force monitor resolution (e.g. 16 = 1920x1080)
|
||||
#hdmi_mode=16
|
||||
# Some displays might have issues with text/pixels spilling off the screen.
|
||||
# If this affects you, uncomment the overscan_* settings and adjust the values
|
||||
#overscan_left=20
|
||||
#overscan_right=12
|
||||
#overscan_top=10
|
||||
#overscan_bottom=10
|
||||
# For i2c & spi
|
||||
dtparam=i2c_arm=on
|
||||
dtparam=spi=on
|
||||
# Memory reserved for the GPU (in MB)
|
||||
mem_gpu=256
|
||||
|
||||
# Enable audio (loads snd_bcm2835)
|
||||
dtparam=audio=on
|
Binary file not shown.
Binary file not shown.
|
@ -1,50 +0,0 @@
|
|||
ARCH="aarch64"
|
||||
BOOT_SOC="rk3568"
|
||||
|
||||
# kernel section
|
||||
KERNEL="https://github.com/armbian/linux-rockchip.git#rk-6.1-rkr4.1"
|
||||
PRESET_CONFIG="kernel_ok3568_defconfig"
|
||||
DTB="dtbs/rockchip/rk3568-ok3568c"
|
||||
|
||||
# u-boot section
|
||||
UBOOT="https://github.com/radxa/u-boot.git"
|
||||
UBOOT_VERSION="next-dev-v2024.03"
|
||||
UBOOT_CONFIG="rk3568-ok3568c_defconfig"
|
||||
|
||||
# cmdline
|
||||
# root=/dev/mmcblk1p2 rootwait rootfstype=ext4 splash=verbose console=ttyS2,1500000 console=tty1 consoleblank=0 loglevel=1 earlycon=uart8250,mmio32,0xfe660000 console=ttyFIQ0 cma=256M androidboot.fwver=bl31-v1.44,uboot-rmbian-201-11/11/2024
|
||||
CMDLINE="earlycon=uart8250,mmio32,0xfeb50000 console=ttyFIQ0 console=tty1 consoleblank=0"
|
||||
EXTRA_PKGS="uboot-tools dracut"
|
||||
|
||||
# disk section
|
||||
# /boot is vfat partition
|
||||
BOOT_FSTYPE="vfat"
|
||||
BOOT_SIZE="256MB"
|
||||
# / is ext4 partition
|
||||
ROOT_SIZE="1500MB"
|
||||
ROOT_FSTYPE="ext4"
|
||||
|
||||
# platform section
|
||||
# # put it in blobs dir
|
||||
RK_DDR="rk3568_ddr_1560MHz_v1.23.bin"
|
||||
BL31="rk3568_bl31_v1.44.elf"
|
||||
UBOOT_BUILD="make KCFLAGS='-Wno-error' BL31={BL31} spl/u-boot-spl.bin u-boot.dtb u-boot.itb CROSS_COMPILE='{ARCH}-linux-gnu-'"
|
||||
MKIMAGE_CMD="tools/mkimage -n {BOOT_SOC} -T rksd -d {RK_DDR}:spl/u-boot-spl.bin idbloader.img"
|
||||
# url to download rockchip bootloader blobs
|
||||
BLOBS_URL="https://github.com/rockchip-linux/rkbin/raw/refs/heads/master/bin/rk35/"
|
||||
BOOT_IDB="idbloader.img"
|
||||
BOOT_ITB="u-boot.itb"
|
||||
UINITRD="yes"
|
||||
|
||||
# make BL31=rk3568_bl31_v1.44.elf spl/u-boot-spl.bin u-boot.dtb u-boot.itb CROSS_COMPILE="aarch64-linux-gnu-"
|
||||
#
|
||||
# dd if=idbloader.img of=/dev/loop1 seek=64 conv=notrunc status=none
|
||||
# dd if=u-boot.itb of=/dev/loop1 seek=16384 conv=notrunc status=none
|
||||
#
|
||||
# sgdisk --zap-all /dev/loop0
|
||||
# sgdisk --new=1:15M:+256M --typecode=1:8300 /dev/loop0
|
||||
# sgdisk --new=2:0:0 --typecode=2:8300 /dev/loop0
|
||||
#
|
||||
# dracut --regenerate-all --force
|
||||
# mkimage -A arm64 -O linux -T ramdisk -C gzip -n uInitrd -d /boot/initramfs-6.1.75.img /boot/uInitrd
|
||||
# mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr
|
File diff suppressed because it is too large
Load diff
33
device/rockchip/ok3568c/mkosi.conf
Normal file
33
device/rockchip/ok3568c/mkosi.conf
Normal file
|
@ -0,0 +1,33 @@
|
|||
[Distribution]
|
||||
Distribution=rosa
|
||||
Release=rosa13
|
||||
Architecture=arm64
|
||||
|
||||
[Output]
|
||||
Format=disk
|
||||
CompressOutput=
|
||||
SectorSize=512
|
||||
|
||||
[Content]
|
||||
Packages=
|
||||
kernel-6.1-rockchip
|
||||
coreutils
|
||||
dnf
|
||||
neovim
|
||||
dracut
|
||||
iproute2
|
||||
locales-en
|
||||
openssh-server
|
||||
rosa-repos
|
||||
systemd
|
||||
uboot-tools
|
||||
|
||||
Bootable=no
|
||||
Autologin=yes
|
||||
RootPassword=root
|
||||
RootShell=/usr/bin/bash
|
||||
Locale=en_US.UTF-8
|
||||
Timezone=Europe/Moscow
|
||||
Hostname=elara
|
||||
WithDocs=no
|
||||
CleanPackageMetadata=false
|
|
@ -1,13 +1,13 @@
|
|||
setenv fdtfile "dtbs/rockchip/rk3568-ok3568c.dtb"
|
||||
|
||||
setenv bootargs "root=/dev/mmcblk1p2 rootwait rootfstype=ext4 splash=verbose console=ttyS2,1500000 console=tty1 consoleblank=0 loglevel=1 earlycon=uart8250,mmio32,0xfe660000 console=ttyFIQ0 cma=256M"
|
||||
setenv bootargs "root=/dev/mmcblk1p3 rootwait rootfstype=ext4 splash=verbose console=ttyS2,1500000 console=tty1 consoleblank=0 loglevel=1 earlycon=uart8250,mmio32,0xfe660000 console=ttyFIQ0 cma=256M"
|
||||
|
||||
test -n "${distro_bootpart}" || distro_bootpart=1
|
||||
|
||||
echo "Boot script loaded from ${devtype} ${devnum}:${distro_bootpart}"
|
||||
|
||||
load ${devtype} ${devnum}:${distro_bootpart} ${ramdisk_addr_r} ${prefix}uInitrd
|
||||
load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} ${prefix}Image
|
||||
load ${devtype} ${devnum}:${distro_bootpart} ${ramdisk_addr_r} ${prefix}INITRD_REPLACE
|
||||
load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} ${prefix}IMAGE_REPLACE
|
||||
load ${devtype} ${devnum}:${distro_bootpart} ${fdt_addr_r} ${prefix}${fdtfile}
|
||||
|
||||
fdt addr ${fdt_addr_r}
|
|
@ -0,0 +1,4 @@
|
|||
# grow up rootfs on first boot
|
||||
[Partition]
|
||||
Type=root
|
||||
GrowFileSystem=yes
|
|
@ -0,0 +1,5 @@
|
|||
[Unit]
|
||||
ConditionFirstBoot=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -0,0 +1,6 @@
|
|||
[Match]
|
||||
Name=en*
|
||||
|
||||
[Network]
|
||||
DHCP=yes
|
||||
IPv6PrivacyExtensions=yes
|
|
@ -0,0 +1,7 @@
|
|||
enable sshd.service
|
||||
enable systemd-networkd.service
|
||||
enable systemd-growfs-root.service
|
||||
|
||||
# We install dnf in some images but it's only going to be used rarely,
|
||||
# so let's not have dnf create its cache.
|
||||
disable dnf-makecache.*
|
4
device/rockchip/ok3568c/mkosi.finalize.d/10-bar.sh.finalyze
Executable file
4
device/rockchip/ok3568c/mkosi.finalize.d/10-bar.sh.finalyze
Executable file
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
set -x
|
||||
env
|
33
device/rockchip/ok3568c/mkosi.postinst.chroot
Executable file
33
device/rockchip/ok3568c/mkosi.postinst.chroot
Executable file
|
@ -0,0 +1,33 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
set -Eeuo pipefail
|
||||
env
|
||||
# install or remove files here
|
||||
# systemctl not working here
|
||||
# systemctl enable sshd
|
||||
# systemctl enable bpftune
|
||||
# systemctl disable dnf-makecache.timer
|
||||
|
||||
version=$(rpm -q --queryformat '%{version}\n' kernel-6.1-rockchip)
|
||||
printf "Generate /boot/uInitrd-${version}...\n"
|
||||
# mkimage -A arm64 -O linux -T ramdisk -C gzip -n uInitrd -d /boot/initrd-%{version}.img /boot/uInitrd
|
||||
mkimage -A arm64 -O linux -T ramdisk -C gzip -d /boot/initrd-${version}.img /boot/uInitrd-${version}
|
||||
|
||||
printf "Remove dracut-generated initrd...\n"
|
||||
rm -fv /boot/initrd-${version}.img
|
||||
rm -fv /boot/uInitrd
|
||||
|
||||
# generate boot.scr
|
||||
# see mkosi.extra/boot/boot.cmd
|
||||
printf "Adjust /boot/boot.cmd for kernel ${version}...\n"
|
||||
sed -i "s!INITRD_REPLACE!uInitrd-${version}!g" /boot/boot.cmd
|
||||
sed -i "s!IMAGE_REPLACE!vmlinuz-${version}!g" /boot/boot.cmd
|
||||
|
||||
printf "Current /boot/boot.cmd...\n"
|
||||
printf "#########################\n"
|
||||
cat /boot/boot.cmd
|
||||
printf "#########################\n"
|
||||
|
||||
printf "Generate /boot/boot.scr...\n"
|
||||
/usr/bin/mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr
|
6
device/rockchip/ok3568c/mkosi.postoutput.d/10-bar.sh.finalyze
Executable file
6
device/rockchip/ok3568c/mkosi.postoutput.d/10-bar.sh.finalyze
Executable file
|
@ -0,0 +1,6 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
set -x
|
||||
env
|
||||
ls -la ${SRCDIR}
|
||||
ls -la ${OUTPUTDIR}
|
5
device/rockchip/ok3568c/mkosi.repart/00-uboot.conf
Normal file
5
device/rockchip/ok3568c/mkosi.repart/00-uboot.conf
Normal file
|
@ -0,0 +1,5 @@
|
|||
[Partition]
|
||||
Type=21686148-6449-6e6f-744e-656564454649
|
||||
Format=
|
||||
SizeMinBytes=15M
|
||||
SizeMaxBytes=15M
|
8
device/rockchip/ok3568c/mkosi.repart/10-esp.conf
Normal file
8
device/rockchip/ok3568c/mkosi.repart/10-esp.conf
Normal file
|
@ -0,0 +1,8 @@
|
|||
[Partition]
|
||||
Type=esp
|
||||
Format=vfat
|
||||
#MountPoint=/boot
|
||||
Label=bootfs
|
||||
SizeMinBytes=256M
|
||||
SizeMaxBytes=256M
|
||||
CopyFiles=/boot:/
|
6
device/rockchip/ok3568c/mkosi.repart/20-root.conf
Normal file
6
device/rockchip/ok3568c/mkosi.repart/20-root.conf
Normal file
|
@ -0,0 +1,6 @@
|
|||
[Partition]
|
||||
Type=root
|
||||
Label=rootfs
|
||||
Format=ext4
|
||||
CopyFiles=/
|
||||
Minimize=guess
|
39
device/rockchip/ok3568c/u-boot/mkosi.build
Executable file
39
device/rockchip/ok3568c/u-boot/mkosi.build
Executable file
|
@ -0,0 +1,39 @@
|
|||
#!/bin/sh
|
||||
set -x
|
||||
|
||||
echo "--- mkosi.build: args=$@"
|
||||
echo "--- mkosi.build: container=$container"
|
||||
|
||||
if [ "$container" != "mkosi" ]; then
|
||||
exec mkosi-chroot "$CHROOT_SCRIPT" "$@"
|
||||
fi
|
||||
|
||||
echo "--- mkosi.build: user=$USER"
|
||||
echo "--- mkosi.build: home=$HOME"
|
||||
echo "--- mkosi.build: pwd=$PWD"
|
||||
echo "--- mkosi.build: srcdir=$SRCDIR"
|
||||
echo "--- mkosi.build: builddir=$BUILDDIR"
|
||||
|
||||
cd $SRCDIR
|
||||
echo "--- mkosi.build: clone u-boot"
|
||||
dnf in -y python2 --release 13
|
||||
git clone https://github.com/radxa/u-boot.git --depth 1 -b next-dev-v2024.03
|
||||
cd u-boot
|
||||
git apply ${SRCDIR}/configuration/*.patch
|
||||
BL31="rk3568_bl31_v1.44.elf"
|
||||
RKDDR="rk3568_ddr_1560MHz_v1.23.bin"
|
||||
BOOT_SOC="rk3568"
|
||||
ARCH="aarch64"
|
||||
|
||||
wget https://github.com/rockchip-linux/rkbin/raw/refs/heads/master/bin/rk35/${RKDDR}
|
||||
wget https://github.com/rockchip-linux/rkbin/raw/refs/heads/master/bin/rk35/${BL31}
|
||||
|
||||
make rk3568-ok3568c_defconfig
|
||||
make -s -j$(nproc) KCFLAGS="-Wno-error" \
|
||||
BL31=${BL31} \
|
||||
spl/u-boot-spl.bin \
|
||||
u-boot.dtb u-boot.itb CROSS_COMPILE="${ARCH}-linux-gnu-"
|
||||
|
||||
tools/mkimage -n ${BOOT_SOC} -T rksd -d ${RKDDR}:spl/u-boot-spl.bin idbloader.img
|
||||
|
||||
cp -fv idbloader.img u-boot.itb ${SRCDIR}/mkosi/
|
27
device/rockchip/ok3568c/u-boot/mkosi.conf
Normal file
27
device/rockchip/ok3568c/u-boot/mkosi.conf
Normal file
|
@ -0,0 +1,27 @@
|
|||
[Distribution]
|
||||
Distribution=rosa
|
||||
Release=rosa13
|
||||
Architecture=x86-64
|
||||
|
||||
[Output]
|
||||
Format=directory
|
||||
|
||||
[Content]
|
||||
Bootable=no
|
||||
Packages=basesystem-build
|
||||
curl
|
||||
dnf
|
||||
git
|
||||
gcc-aarch64-linux-gnu
|
||||
binutils-aarch64-linux-gnu
|
||||
wget
|
||||
dtc
|
||||
bc
|
||||
rosa-repos-contrib
|
||||
rosa-repos
|
||||
|
||||
|
||||
[Build]
|
||||
WithNetwork=yes
|
||||
BuildSources=./:mkosi
|
||||
./configuration:configuration
|
|
@ -1,109 +0,0 @@
|
|||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from utils.common import load_config
|
||||
|
||||
|
||||
def load_bootstrap_config(bootstrap_path):
|
||||
"""Load the bootstrap configuration from the specified file."""
|
||||
config = {}
|
||||
with open(bootstrap_path, "r") as f:
|
||||
for line in f:
|
||||
if "=" in line and not line.strip().startswith("#"):
|
||||
key, value = line.strip().split("=", 1)
|
||||
config[key] = value.strip('"')
|
||||
return config
|
||||
|
||||
|
||||
def generate_dnf_conf(dnf_conf_path, abf_downloads, release):
|
||||
"""Generate dnf.conf based on the bootstrap configuration."""
|
||||
dnf_conf_content = f"""
|
||||
[main]
|
||||
keepcache=1
|
||||
debuglevel=2
|
||||
reposdir=/dev/null
|
||||
retries=20
|
||||
obsoletes=1
|
||||
gpgcheck=0
|
||||
assumeyes=1
|
||||
syslog_ident=mock
|
||||
syslog_device=
|
||||
install_weak_deps=0
|
||||
metadata_expire=60s
|
||||
best=1
|
||||
|
||||
[{release}_main_release]
|
||||
name={release}_main_release
|
||||
baseurl={abf_downloads}/{release}/repository/aarch64/main/release
|
||||
gpgcheck=0
|
||||
enabled=1
|
||||
|
||||
[{release}_main_updates]
|
||||
name={release}_main_updates
|
||||
baseurl={abf_downloads}/{release}/repository/aarch64/main/updates
|
||||
gpgcheck=0
|
||||
enabled=1
|
||||
"""
|
||||
|
||||
os.makedirs(os.path.dirname(dnf_conf_path), exist_ok=True)
|
||||
with open(dnf_conf_path, "w") as f:
|
||||
f.write(dnf_conf_content)
|
||||
|
||||
|
||||
def run_dnf_install(config, dnf_conf_path, rootfs_dir, arch, extra_pkgs=""):
|
||||
"""Run dnf command to install packages based on the bootstrap configuration."""
|
||||
pkgs = config["PKGS"]
|
||||
weak_deps = config["WEAK_DEPS"].lower()
|
||||
if extra_pkgs:
|
||||
pkgs += f" {extra_pkgs}"
|
||||
|
||||
print(f"Bootstrapping '{arch}' rootfs...")
|
||||
dnf_command = [
|
||||
"sudo",
|
||||
"dnf",
|
||||
"--setopt=install_weak_deps=" + str(weak_deps),
|
||||
"--config", dnf_conf_path,
|
||||
"--nodocs",
|
||||
"--forcearch", arch,
|
||||
"--installroot", rootfs_dir,
|
||||
"install"
|
||||
] + pkgs.split()
|
||||
|
||||
subprocess.run(dnf_command, check=True, stdout=subprocess.DEVNULL)
|
||||
|
||||
|
||||
def set_root_password_with_systemd(rootfs_dir, password_root):
|
||||
"""Set root password using systemd-firstboot in chroot environment."""
|
||||
subprocess.run(
|
||||
["sudo", "systemd-firstboot", "--root-password=", password_root, "--root=", rootfs_dir],
|
||||
check=True
|
||||
)
|
||||
print(f"root password set to '{password_root}' in chroot at {rootfs_dir}")
|
||||
|
||||
|
||||
def setup_bootstrap(bootstrap_dir, tmp_dir, vendor, device, distro, arch):
|
||||
# load distro config
|
||||
# bootstrap/DISTRO_NAME
|
||||
distro_config_path = os.path.join(bootstrap_dir, distro)
|
||||
|
||||
if not os.path.exists(distro_config_path):
|
||||
print(f"Bootstrap configuration for distro '{distro}' not found.")
|
||||
current_directory = os.getcwd()
|
||||
print(f"Текущая рабочая директория: {current_directory}")
|
||||
sys.exit(1)
|
||||
|
||||
config = load_config(distro_config_path)
|
||||
|
||||
device_config_path = os.path.join("device", vendor, device, "config")
|
||||
device_config = load_config(device_config_path) if os.path.exists(device_config_path) else {}
|
||||
|
||||
extra_pkgs = device_config.get("EXTRA_PKGS", "")
|
||||
|
||||
dnf_conf_path = os.path.join(tmp_dir, vendor, device, "dnf.conf")
|
||||
rootfs_dir = os.path.join(tmp_dir, vendor, device, "rootfs")
|
||||
|
||||
generate_dnf_conf(dnf_conf_path, config["ABF_DOWNLOADS"], config["RELEASE"])
|
||||
run_dnf_install(config, dnf_conf_path, rootfs_dir, arch, extra_pkgs)
|
||||
set_root_password_with_systemd(rootfs_dir, config["PASSWD_ROOT"])
|
||||
|
||||
#setup_user(rootfs_dir, config["DEFAULT_USER"], config["DEFAULT_USER_PASSWORD"], config["PASSWD_ROOT"])
|
|
@ -1,34 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
import os
|
||||
import subprocess
|
||||
from urllib.request import urlretrieve
|
||||
|
||||
def load_config(config_path):
|
||||
config = {}
|
||||
with open(config_path, "r") as f:
|
||||
for line in f:
|
||||
if "=" in line and not line.strip().startswith("#"):
|
||||
key, value = line.strip().split("=", 1)
|
||||
config[key] = value.strip('"')
|
||||
return config
|
||||
|
||||
|
||||
def clone_repo(repo_url, branch, dest_dir, name):
|
||||
if os.path.exists(dest_dir):
|
||||
print(f"Warning: {name} directory '{dest_dir}' already exists. Skipping clone.")
|
||||
else:
|
||||
os.makedirs(dest_dir, exist_ok=True)
|
||||
subprocess.run(["git", "clone", "--depth", "1", repo_url, "-b", branch, dest_dir], check=True)
|
||||
|
||||
|
||||
def download_blob(blob_url, destination):
|
||||
"""Download a file from the given URL and save it to the destination."""
|
||||
try:
|
||||
print(f"Downloading {blob_url} to {destination}...")
|
||||
os.makedirs(os.path.dirname(destination), exist_ok=True)
|
||||
urlretrieve(blob_url, destination)
|
||||
print(f"Downloaded: {destination}")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Warning: Unable to download {blob_url}. {e}")
|
||||
return False
|
|
@ -1,127 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import shutil
|
||||
#from common import load_config
|
||||
|
||||
def get_kernel_version(kernel_dir):
|
||||
"""Extract kernel version by running 'make kernelversion' in the kernel directory."""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["make", "kernelversion"],
|
||||
cwd=kernel_dir,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
check=True
|
||||
)
|
||||
return result.stdout.strip()
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error: Failed to get kernel version from {kernel_dir}")
|
||||
print(e.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def generate_spec_file(TMP_DIR, config, vendor, device):
|
||||
"""Generate RPM spec file from template and config"""
|
||||
# Load device config
|
||||
config_path = os.path.join("device", vendor, device, "config")
|
||||
if not os.path.exists(config_path):
|
||||
print(f"Error: Config file not found at {config_path}")
|
||||
sys.exit(1)
|
||||
|
||||
# Load template
|
||||
template_path = os.path.join("utils", "kernel.template")
|
||||
if not os.path.exists(template_path):
|
||||
print(f"Error: Template file not found at {template_path}")
|
||||
sys.exit(1)
|
||||
|
||||
with open(template_path, 'r') as f:
|
||||
template = f.read()
|
||||
|
||||
# Extract kernel version from kernel URL and branch
|
||||
kernel_url, kernel_branch = config["KERNEL"].split("#")
|
||||
|
||||
# Extract kernel version from Makefile
|
||||
kernel_dir = os.path.join(TMP_DIR, vendor, device, "kernel")
|
||||
if not os.path.exists(kernel_dir):
|
||||
print(f"Error: Kernel directory not found at {kernel_dir}")
|
||||
sys.exit(1)
|
||||
|
||||
kernel_version = get_kernel_version(kernel_dir)
|
||||
|
||||
# Determine KERNEL_ARCH and CROSS_COMPILE based on ARCH
|
||||
arch = config.get("ARCH", "unknown")
|
||||
kernel_config = config.get("KERNEL_CONFIG", "unknown")
|
||||
if arch == "aarch64":
|
||||
kernel_arch = "arm64"
|
||||
cross_compile = "aarch64-linux-gnu"
|
||||
else:
|
||||
kernel_arch = arch
|
||||
cross_compile = f"{arch}-linux-gnu" # Default cross compile format
|
||||
|
||||
# Prepare replacements
|
||||
device_name = f"{vendor}-{device}"
|
||||
replacements = {
|
||||
"{BOARD_NAME}": device_name,
|
||||
"{KERNEL_VERSION}": kernel_version,
|
||||
"{DEVICE_NAME}": device_name,
|
||||
"{KERNEL_ARCH}": kernel_arch,
|
||||
"{ARCH}": arch, # Add ARCH replacement
|
||||
"{KERNEL_CONFIG}": kernel_config,
|
||||
"{CROSS_COMPILE}": cross_compile # Add CROSS_COMPILE replacement
|
||||
}
|
||||
|
||||
# Handle Source1 based on PRESET_CONFIG
|
||||
preset_config = config.get("PRESET_CONFIG", "").strip()
|
||||
if preset_config:
|
||||
replacements["{Source1}"] = f"Source1: {preset_config}" # Format Source1 correctly
|
||||
replacements["{SOURCE1_COMMAND}"] = "cp %{S:1} .config"
|
||||
else:
|
||||
replacements["{Source1}"] = "" # Leave Source1 empty if PRESET_CONFIG is not set
|
||||
replacements["{SOURCE1_COMMAND}"] = ""
|
||||
|
||||
kernel_defconfig = config.get("KERNEL_CONFIG", "").strip()
|
||||
if kernel_defconfig:
|
||||
replacements["{MAKE_DEFCONFIG}"] = f"%make_build {kernel_defconfig} ARCH={kernel_arch}" # Format Source1 correctly
|
||||
else:
|
||||
replacements["{MAKE_DEFCONFIG}"] = ""
|
||||
|
||||
# Apply replacements
|
||||
spec_content = template
|
||||
for key, value in replacements.items():
|
||||
spec_content = spec_content.replace(key, value)
|
||||
|
||||
# Define output directory and path
|
||||
output_dir = os.path.join(TMP_DIR, vendor, device, "kernel-build")
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
# Copy PRESET_CONFIG file if it exists
|
||||
if preset_config:
|
||||
preset_config_path = os.path.join("device", vendor, device, preset_config)
|
||||
if os.path.exists(preset_config_path):
|
||||
shutil.copy(preset_config_path, output_dir)
|
||||
print(f"Copied {preset_config} to {output_dir}")
|
||||
else:
|
||||
print(f"Warning: PRESET_CONFIG file {preset_config_path} not found.")
|
||||
|
||||
# Write spec file
|
||||
spec_file_path = os.path.join(output_dir, f"kernel-{device_name}.spec")
|
||||
with open(spec_file_path, 'w') as f:
|
||||
f.write(spec_content)
|
||||
|
||||
print(f"Generated spec file: {spec_file_path}")
|
||||
return spec_file_path
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 3:
|
||||
print("Usage: generate_spec.py <vendor> <device>")
|
||||
sys.exit(1)
|
||||
|
||||
vendor = sys.argv[1]
|
||||
device = sys.argv[2]
|
||||
|
||||
generate_spec_file(vendor, device)
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from utils.common import clone_repo
|
||||
from utils.patch import apply_kernel_patches
|
||||
|
||||
|
||||
def clone_kernel(TMP_DIR, BASE_DIR, config, vendor, device, kernel_dir):
|
||||
kernel_git = config.get("KERNEL").split("#")[0]
|
||||
kernel_branch = config.get("KERNEL").split("#")[1]
|
||||
clone_repo(kernel_git, kernel_branch, kernel_dir, "kernel")
|
||||
apply_kernel_patches(BASE_DIR, vendor, device, kernel_dir)
|
||||
|
||||
|
||||
def make_kernel_tar(kernel_dir, kernel_rpm_dir):
|
||||
base_dir = os.getcwd()
|
||||
os.chdir(kernel_dir)
|
||||
subprocess.run(["git", "archive",
|
||||
"--format=tar", "--prefix=kernel/",
|
||||
f"--output={kernel_rpm_dir}/kernel.tar", "HEAD"])
|
||||
os.chdir(base_dir)
|
|
@ -1,46 +0,0 @@
|
|||
%global debug_package %{nil}
|
||||
%global _build_pkgcheck_set %nil
|
||||
%global _build_pkgcheck_srpm %nil
|
||||
%global _modulesdir /usr/lib/modules
|
||||
|
||||
Name: kernel-{BOARD_NAME}
|
||||
Version: {KERNEL_VERSION}
|
||||
Release: 1
|
||||
Summary: kernel for {BOARD_NAME} devices
|
||||
Group: System/Kernel and hardware
|
||||
Source0: kernel.tar
|
||||
# This line will be conditionally included or removed
|
||||
{Source1}
|
||||
License: GPLv2
|
||||
Provides: kernel = %{EVRD}
|
||||
|
||||
%description
|
||||
kernel for {BOARD_NAME}
|
||||
|
||||
%prep
|
||||
%autosetup -p1 -n kernel
|
||||
|
||||
# If Source1 is defined, include this line
|
||||
{SOURCE1_COMMAND}
|
||||
|
||||
grep -Irl /lib/modules | xargs sed -i -e 's,/lib/modules,%{_modulesdir},g' -e 's,/usr/usr/lib/modules,/usr/lib/modules,g'
|
||||
|
||||
%build
|
||||
{MAKE_DEFCONFIG}
|
||||
%make_build -s CROSS_COMPILE=/usr/bin/{ARCH}-linux-gnu- ARCH={KERNEL_ARCH}
|
||||
|
||||
%install
|
||||
# Install kernel modules, if any
|
||||
make V=1 modules_install ARCH={KERNEL_ARCH} \
|
||||
INSTALL_MOD_PATH=%{buildroot} \
|
||||
INSTALL_DTBS_PATH=%{buildroot}/boot/dtbs
|
||||
|
||||
make dtbs_install ARCH={KERNEL_ARCH} \
|
||||
INSTALL_MOD_PATH=%{buildroot} \
|
||||
INSTALL_DTBS_PATH=%{buildroot}/boot/dtbs
|
||||
|
||||
cp arch/arm64/boot/Image %{buildroot}/boot/vmlinuz-%{version}
|
||||
|
||||
%files
|
||||
/boot/*
|
||||
%{_modulesdir}/*
|
|
@ -1,116 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
def create_disk_image(tmp_dir, config, vendor, device):
|
||||
|
||||
boot_size = config.get("BOOT_SIZE", "").rstrip("MB")
|
||||
root_size = config.get("ROOT_SIZE", "0").rstrip("MB")
|
||||
|
||||
if not root_size:
|
||||
print("Error: ROOT_SIZE is not defined in the configuration.")
|
||||
return
|
||||
|
||||
if not boot_size:
|
||||
boot_size = "0"
|
||||
|
||||
disk_image_path = os.path.join(tmp_dir, vendor, device, "disk.img")
|
||||
os.makedirs(os.path.dirname(disk_image_path), exist_ok=True)
|
||||
cmd = [
|
||||
"dd",
|
||||
"if=/dev/zero",
|
||||
f"of={disk_image_path}",
|
||||
"bs=1M",
|
||||
f"count={int(boot_size) + int(root_size)}"
|
||||
]
|
||||
|
||||
print(f"Creating disk image: {disk_image_path} size {root_size} MB")
|
||||
subprocess.run(cmd, check=True)
|
||||
print(f"Disk image created at {disk_image_path}")
|
||||
return disk_image_path
|
||||
|
||||
|
||||
def cleanup_loop_devices():
|
||||
result = subprocess.run(["losetup", "-l", "-O", "NAME"], capture_output=True, text=True)
|
||||
active_loops = result.stdout.splitlines()[1:]
|
||||
|
||||
for loop_device in active_loops:
|
||||
loop_device = loop_device.strip()
|
||||
if loop_device:
|
||||
print(f"Detaching {loop_device}")
|
||||
subprocess.run(["losetup", "-d", loop_device], check=False)
|
||||
|
||||
|
||||
def setup_loop_device(disk_image_path):
|
||||
cleanup_loop_devices()
|
||||
|
||||
cmd = ["losetup", "-fP", "--show", disk_image_path]
|
||||
result = subprocess.run(cmd, check=True, capture_output=True, text=True)
|
||||
loop_device = result.stdout.strip()
|
||||
print(f"Disk image mounted to loop device {loop_device}")
|
||||
return loop_device
|
||||
|
||||
def create_partitions(loop_device, config):
|
||||
root_size = config.get("ROOT_SIZE", "1024MB").rstrip("MB")
|
||||
root_fstype = config.get("ROOT_FSTYPE", "ext4")
|
||||
boot_size = config.get("BOOT_SIZE", "0").rstrip("MB") # Default to 0 if not specified
|
||||
boot_fstype = config.get("BOOT_FSTYPE", "ext4") # Default to ext4 if not specified
|
||||
|
||||
print(f"Creating partitions on {loop_device} using sgdisk...")
|
||||
|
||||
try:
|
||||
# Clear existing partitions
|
||||
subprocess.run(["sgdisk", "--zap-all", loop_device], check=True)
|
||||
|
||||
if int(boot_size) > 0:
|
||||
# Create boot partition
|
||||
# 16M here s empty space for u-boot
|
||||
subprocess.run(["sgdisk",
|
||||
"--new=1:16M:+{}M".format(boot_size),
|
||||
"--typecode=1:8300", loop_device], check=True)
|
||||
|
||||
# Create root partition
|
||||
subprocess.run(["sgdisk",
|
||||
"--new=2:0:0",
|
||||
"--typecode=2:8300", loop_device], check=True)
|
||||
|
||||
# Format partitions
|
||||
if boot_fstype == "vfat":
|
||||
subprocess.run(["mkfs.vfat", "-F", "32", f"{loop_device}p1"], check=True)
|
||||
else:
|
||||
subprocess.run(["mkfs.ext4", f"{loop_device}p1"], check=True)
|
||||
subprocess.run(["mkfs.ext4", f"{loop_device}p2"], check=True)
|
||||
|
||||
print(f" - Boot partition ({boot_size}MB) created and formatted as {boot_fstype}")
|
||||
print(f" - Root partition created and formatted as {root_fstype}")
|
||||
|
||||
else:
|
||||
# Create single root partition
|
||||
subprocess.run(["sgdisk", "--new=1:0:0", "--typecode=1:8300", loop_device], check=True)
|
||||
subprocess.run(["mkfs.ext4", f"{loop_device}p1"], check=True)
|
||||
print(f" - Single root partition created and formatted as {root_fstype}")
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error creating partitions with sgdisk: {e}")
|
||||
return False
|
||||
|
||||
print("Partitioning and formatting complete.")
|
||||
return True
|
||||
|
||||
def mount_partitions(config, loop_device, tmp_dir, vendor, device):
|
||||
rootfs_dir = os.path.join(tmp_dir, vendor, device, "rootfs")
|
||||
os.makedirs(rootfs_dir, exist_ok=True)
|
||||
boot_partition = f"{loop_device}p1"
|
||||
root_partition = f"{loop_device}p2" if "BOOT_SIZE" in config else f"{loop_device}p1"
|
||||
|
||||
print(f"Mounting root (/) partition at {rootfs_dir}")
|
||||
subprocess.run(["mount", root_partition, rootfs_dir], check=True)
|
||||
|
||||
if "BOOT_SIZE" in config:
|
||||
boot_dir = os.path.join(rootfs_dir, "boot")
|
||||
os.makedirs(boot_dir, exist_ok=True)
|
||||
print(f"Mounting /boot partition at {boot_dir}")
|
||||
subprocess.run(["mount", boot_partition, boot_dir], check=True)
|
||||
|
||||
print("Mounting complete.")
|
|
@ -1,60 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
def apply_patches(patch_dir, target_dir):
|
||||
"""
|
||||
Applies patches from the specified patch directory to the target directory using `git apply`.
|
||||
"""
|
||||
if not os.path.exists(patch_dir):
|
||||
print(f"No patches directory found at {patch_dir}. Skipping patch application.")
|
||||
return
|
||||
|
||||
patches = sorted(os.listdir(patch_dir))
|
||||
|
||||
if not patches:
|
||||
print(f"No patches found in {patch_dir}. Skipping patch application.")
|
||||
return
|
||||
|
||||
print(f"Applying patches from {patch_dir} to {target_dir}...")
|
||||
|
||||
for patch in patches:
|
||||
patch_path = os.path.join(patch_dir, patch)
|
||||
if os.path.isfile(patch_path):
|
||||
print(f"Applying patch: {patch}")
|
||||
try:
|
||||
check_result = subprocess.run(
|
||||
["git", "apply", "--check", patch_path],
|
||||
cwd=target_dir,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
)
|
||||
|
||||
if check_result.returncode != 0:
|
||||
print(f"Warning: Patch {patch} has already been applied or conflicts exist. Skipping.")
|
||||
continue
|
||||
|
||||
subprocess.run(["git", "apply", patch_path], cwd=target_dir, check=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Failed to apply patch {patch}: {e}")
|
||||
else:
|
||||
print(f"Skipping non-file item: {patch_path}")
|
||||
|
||||
|
||||
def apply_kernel_patches(base_dir, vendor, device, kernel_dir):
|
||||
"""
|
||||
Apply kernel patches for the specified vendor and device.
|
||||
"""
|
||||
patch_dir = os.path.join(base_dir, "device", vendor, device, "patches", "kernel")
|
||||
apply_patches(patch_dir, kernel_dir)
|
||||
|
||||
|
||||
def apply_uboot_patches(base_dir, vendor, device, uboot_dir):
|
||||
"""
|
||||
Apply U-Boot patches for the specified vendor and device.
|
||||
"""
|
||||
patch_dir = os.path.join(base_dir, "device", vendor, device, "patches", "u-boot")
|
||||
apply_patches(patch_dir, uboot_dir)
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
|
||||
def run_rpmbuild(kernel_build_dir, target_arch):
|
||||
"""Run rpmbuild for the given kernel build directory and target architecture."""
|
||||
# Ensure the kernel-build directory exists
|
||||
if not os.path.isdir(kernel_build_dir):
|
||||
print(f"Error: Kernel build directory '{kernel_build_dir}' does not exist.")
|
||||
sys.exit(1)
|
||||
|
||||
base_dir = os.getcwd()
|
||||
# Change to the kernel-build directory
|
||||
os.chdir(kernel_build_dir)
|
||||
|
||||
# Check if a spec file exists
|
||||
spec_files = [f for f in os.listdir(kernel_build_dir) if f.endswith(".spec")]
|
||||
if not spec_files:
|
||||
print(f"Error: No spec files found in '{kernel_build_dir}'.")
|
||||
sys.exit(1)
|
||||
elif len(spec_files) > 1:
|
||||
print(f"Warning: Multiple spec files found in '{kernel_build_dir}'. Using '{spec_files[0]}'.")
|
||||
|
||||
# Use the first spec file found
|
||||
spec_file = spec_files[0]
|
||||
|
||||
# Define paths for RPM build directories
|
||||
rpmdir = os.path.join(kernel_build_dir, "RPMS")
|
||||
builddir = os.path.join(kernel_build_dir, "BUILD")
|
||||
os.makedirs(rpmdir, exist_ok=True)
|
||||
os.makedirs(builddir, exist_ok=True)
|
||||
|
||||
# Construct the rpmbuild command
|
||||
rpmbuild_command = [
|
||||
"rpmbuild", "-ba",
|
||||
f"--target={target_arch}",
|
||||
f"--define", f"_sourcedir {kernel_build_dir}",
|
||||
f"--define", f"_rpmdir {rpmdir}",
|
||||
f"--define", f"_builddir {builddir}",
|
||||
spec_file
|
||||
]
|
||||
|
||||
# Run the rpmbuild command
|
||||
try:
|
||||
print(f"Running rpmbuild for spec file: {spec_file} with target architecture: {target_arch}")
|
||||
#subprocess.run(rpmbuild_command, check=True)
|
||||
subprocess.run(
|
||||
rpmbuild_command,
|
||||
stdin=subprocess.DEVNULL, # Отключение ввода
|
||||
stdout=sys.stdout, # Вывод в стандартный поток
|
||||
stderr=sys.stderr, # Вывод ошибок
|
||||
check=True
|
||||
)
|
||||
print(f"RPM build completed successfully. RPMs are located in: {rpmdir}")
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error: rpmbuild failed with error code {e.returncode}")
|
||||
sys.exit(1)
|
||||
# go back to script dir
|
||||
os.chdir(base_dir)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 3:
|
||||
print("Usage: rpmbuild.py <kernel-build-dir> <target-arch>")
|
||||
sys.exit(1)
|
||||
|
||||
kernel_build_dir = sys.argv[1]
|
||||
target_arch = sys.argv[2]
|
||||
run_rpmbuild(kernel_build_dir, target_arch)
|
106
utils/uboot.py
106
utils/uboot.py
|
@ -1,106 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from utils.common import clone_repo
|
||||
from utils.common import download_blob
|
||||
from utils.patch import apply_uboot_patches
|
||||
|
||||
def build_uboot(TMP_DIR, BASE_DIR, config, vendor, device):
|
||||
uboot_git = config.get("UBOOT")
|
||||
uboot_branch = config.get("UBOOT_VERSION")
|
||||
uboot_config = config.get("UBOOT_CONFIG")
|
||||
uboot_build_cmd = config.get("UBOOT_BUILD")
|
||||
mkimage_cmd = config.get("MKIMAGE_CMD")
|
||||
blobs_url = config.get("BLOBS_URL", "")
|
||||
uboot_dir = os.path.join(TMP_DIR, vendor, device, "u-boot")
|
||||
|
||||
if "UBOOT" not in config or "UBOOT_VERSION" not in config:
|
||||
print("U-Boot configuration not found. Skipping U-Boot build.")
|
||||
return
|
||||
|
||||
# Clone U-Boot repository
|
||||
clone_repo(uboot_git, uboot_branch, uboot_dir, "u-boot")
|
||||
apply_uboot_patches(BASE_DIR, vendor, device, uboot_dir)
|
||||
|
||||
# Download RK_DDR blob to uboot_dir
|
||||
rk_ddr = None
|
||||
if "RK_DDR" in config:
|
||||
rk_ddr = os.path.join(uboot_dir, os.path.basename(config.get("RK_DDR")))
|
||||
rk_ddr_url = os.path.join(blobs_url, os.path.basename(rk_ddr))
|
||||
if not os.path.isfile(rk_ddr):
|
||||
if not download_blob(rk_ddr_url, rk_ddr):
|
||||
print(f"Warning: RK_DDR blob {rk_ddr_url} could not be downloaded.")
|
||||
|
||||
# Download BL31 blob to uboot_dir
|
||||
bl31 = None
|
||||
if "BL31" in config:
|
||||
bl31 = os.path.join(uboot_dir, os.path.basename(config.get("BL31")))
|
||||
bl31_url = os.path.join(blobs_url, os.path.basename(bl31))
|
||||
if not os.path.isfile(bl31):
|
||||
if not download_blob(bl31_url, bl31):
|
||||
print(f"Warning: BL31 blob {bl31_url} could not be downloaded.")
|
||||
|
||||
# Build U-Boot
|
||||
os.chdir(uboot_dir)
|
||||
try:
|
||||
print(f"Building U-Boot for {vendor}/{device} {uboot_config}...")
|
||||
subprocess.run(["make", uboot_config], check=True)
|
||||
|
||||
# Format U-Boot build command
|
||||
build_command = uboot_build_cmd.format(
|
||||
BL31=bl31 or "",
|
||||
ARCH=config.get("ARCH", "aarch64")
|
||||
)
|
||||
subprocess.run(build_command, shell=True, check=True)
|
||||
|
||||
# Format mkimage command
|
||||
mkimage_command = mkimage_cmd.format(
|
||||
BOOT_SOC=config.get("BOOT_SOC", ""),
|
||||
RK_DDR=rk_ddr or ""
|
||||
)
|
||||
print(mkimage_command)
|
||||
subprocess.run(mkimage_command, shell=True, check=True)
|
||||
|
||||
print("U-Boot build completed successfully.")
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error during U-Boot build: {e}")
|
||||
os.chdir(BASE_DIR)
|
||||
|
||||
def flash_uboot(loop_device, TMP_DIR, config, vendor, device):
|
||||
"""
|
||||
Flash U-Boot components to the disk image.
|
||||
Parameters:
|
||||
loop_device (str): The loop device path (e.g., /dev/loop0).
|
||||
uboot_dir (str): Directory where U-Boot artifacts are located.
|
||||
config (dict): Configuration dictionary.
|
||||
"""
|
||||
uboot_dir = os.path.join(TMP_DIR, vendor, device, "u-boot")
|
||||
idbloader_path = os.path.join(uboot_dir, config.get("BOOT_IDB", "idbloader.img"))
|
||||
uboot_itb_path = os.path.join(uboot_dir, config.get("BOOT_ITB", "u-boot.itb"))
|
||||
|
||||
if not os.path.isfile(idbloader_path) or not os.path.isfile(uboot_itb_path):
|
||||
print(f"Error: Required U-Boot files not found: {idbloader_path}, {uboot_itb_path}")
|
||||
return False
|
||||
|
||||
try:
|
||||
print(f"Flashing {idbloader_path} to {loop_device}...")
|
||||
subprocess.run([
|
||||
"dd", f"if={idbloader_path}", f"of={loop_device}", "seek=64",
|
||||
"conv=notrunc", "status=none"
|
||||
], check=True)
|
||||
|
||||
print(f"Flashing {uboot_itb_path} to {loop_device}...")
|
||||
subprocess.run([
|
||||
"dd", f"if={uboot_itb_path}", f"of={loop_device}", "seek=16384",
|
||||
"conv=notrunc", "status=none"
|
||||
], check=True)
|
||||
|
||||
print("U-Boot flashing completed successfully.")
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error flashing U-Boot files: {e}")
|
||||
return False
|
||||
|
||||
return True
|
Loading…
Add table
Reference in a new issue