Skip to content

Instantly share code, notes, and snippets.

@minlexx
Last active October 3, 2024 16:14
Show Gist options
  • Save minlexx/c15330839133522047e36ce1f0d32059 to your computer and use it in GitHub Desktop.
Save minlexx/c15330839133522047e36ce1f0d32059 to your computer and use it in GitHub Desktop.
Linux build scripts for postmarketOS (read HOWTO-use.txt)
#!/bin/bash
#set -x
codename=$1
rootfs_name=$codename
# Empty codename?
if [[ "x${codename}" = "x" ]]; then
codename="xiaomi-lavender-tianma"
fi
case ${codename} in
"xiaomi-lavender-tianma" | "xiaomi-lavender-boe")
rootfs_name="xiaomi-lavender"
;;
"xiaomi-clover" | "xiaomi-clover-plus")
rootfs_name="xiaomi-clover"
;;
*)
echo "Unknown codename: ${codename} !"
exit 1
;;
esac
cp -v -i ~/.local/var/pmbootstrap/chroot_rootfs_${rootfs_name}/boot/initramfs ./initramfs-${codename}.cpio.gz
ls --color ./initramfs*
du -hs ./initramfs*
#!/bin/bash
# verbose output of all commands
#set -x
codename=$1
if [[ "x${codename}" = "x" ]]; then
codename="xiaomi-lavender-tianma"
fi
INITFS_FILE=initramfs-${codename}-new.cpio.gz
DTB=./arch/arm64/boot/dts/qcom/sdm660-${codename}.dtb
KERNEL=./arch/arm64/boot/Image.gz
KERNEL_DTB=${KERNEL}-dtb
OUT_BOOTIMG=boot-${codename}-mainline.img
echo "Appending dtb: cat ${KERNEL} ${DTB} > ${KERNEL_DTB}"
cat ${KERNEL} ${DTB} > ${KERNEL_DTB}
#deviceinfo_kernel_cmdline="debug earlycon ignore_loglevel clk_ignore_unused pd_ignore_unused fw_devlink=permissive"
deviceinfo_kernel_cmdline="debug earlycon ignore_loglevel"
deviceinfo_flash_offset_base="0x00000000"
deviceinfo_flash_offset_kernel="0x00008000"
deviceinfo_flash_offset_ramdisk="0x01000000"
deviceinfo_flash_offset_second="0x00f00000"
deviceinfo_flash_offset_tags="0x00000100"
deviceinfo_flash_pagesize="4096"
echo "Creating ${OUT_BOOTIMG} using DTB ${DTB} and initramfs ${INITFS_FILE}"
mkbootimg \
--kernel ${KERNEL_DTB} \
--ramdisk ${INITFS_FILE} \
--base "${deviceinfo_flash_offset_base}" \
--second_offset "${deviceinfo_flash_offset_second}" \
--cmdline "${deviceinfo_kernel_cmdline}" \
--kernel_offset "${deviceinfo_flash_offset_kernel}" \
--ramdisk_offset "${deviceinfo_flash_offset_ramdisk}" \
--tags_offset "${deviceinfo_flash_offset_tags}" \
--pagesize "${deviceinfo_flash_pagesize}" \
-o ${OUT_BOOTIMG}
aes
btrfs
crc32_generic
crc32c_generic
dm-crypt
evdev
ext4
f2fs
kernel/arch/arm64/crypto/
kernel/crypto/
overlay
libaes
loop
nls_ascii
nls_cp437
nls_iso8859-1
nls_utf8
uinput
usb_f_rndis
usb_f_ncm
usb-storage
vfat
xts
#!/bin/bash
# See:
# https://www.linaro.org/blog/tips-and-tricks-for-validating-devicetree-sources-with-the-devicetree-schema/
codename=$1
if [[ "x${codename}" = "x" ]]; then
codename="xiaomi-lavender"
fi
# DT_SCHEMA_FILES=iommu/arm,smmu.yaml \
./make.sh \
CHECK_DTBS=y \
qcom/sdm660-${codename}.dtb
#!/bin/bash
codename=$1
if [[ "x${codename}" = "x" ]]; then
codename="xiaomi-lavender-tianma"
fi
echo fastboot flash boot boot-${codename}-mainline.img
fastboot flash boot boot-${codename}-mainline.img
sleep 1
fastboot reboot
# First step, perform "pmbootstrap install" locally once for your device,
# to get the initramfs file generated by pmbootstrap.
# Then copy it into build dir (this is done only once!):
$ ./cp-initfs.sh
# Then regular build process:
$ ./menuconfig.sh or ./make.sh oldconfig
$ ./make.sh && ./modules-install.sh && ./replace-modules-in-initfs.sh xiaomi-lavender-tianma && ./create-bootimg.sh xiaomi-lavender-tianma && ./upload-modules-rsync.sh
# reboot into download mode (hold buttons combo, or run on device: reboot-mode bootloader)
./flash-and-reboot.sh xiaomi-lavender-tianma
#!/usr/bin/python3
from dataclasses import dataclass, field
import os
from pathlib import Path
import shutil
import sys
from typing import List
@dataclass
class ModInfo:
# Short module name, e.g "msm" or "msm.ko"
name: str
# Relative path when found in modules.dep, e.g. "kernel/drivers/gpu/drm/msm/msm.ko.gz"
rel_path: str = ""
# Deps list, e.g. ['kernel/drivers/gpu/drm/drm_exec.ko.gz', ... ])
deps: List[str] = field(default_factory=list)
def print_usage() -> None:
print('Usage:\n\n {} MODULE_NAME SRC_DIR DST_DIR\n'.format(sys.argv[0]))
print('SRC_DIR must contain modules.dep file.')
print('Example:\n\n {} msm INSTALL_PREFIX/lib/modules/6.9.9-sdm660 initfs/lib/modules/6.9.9-sdm660\n'.format(sys.argv[0]))
def read_modules_builtin(src_dir: Path) -> List[str]:
ret = []
builtins_file = src_dir / 'modules.builtin'
with builtins_file.open("rt") as f:
for line in f.readlines():
line = line.strip()
# ^^ "kernel/arch/arm64/crypto/aes-arm64.ko"
# mod_name = Path(line).name # -> "aes-arm64.ko"
mod_name = Path(line).stem # -> "aes-arm64"
ret.append(str(mod_name))
return ret
def find_module_and_deps(short_name: str, src: Path) -> ModInfo | None:
mod_file_name: str = short_name
# Full module file name might also end in .ko.gz,
# but in this case it doesn't matter for sub-string search
if '.ko' not in mod_file_name:
mod_file_name = short_name + '.ko'
dep_file: Path = src / 'modules.dep'
info: ModInfo = ModInfo(short_name)
with dep_file.open("rt") as f:
for line in f.readlines():
# Example of line in modules.dep:
# kernel/arch/arm64/crypto/chacha-neon.ko.gz: kernel/lib/crypto/libchacha.ko.gz
line = line.strip()
parts = line.split(':')
# Either full match or sub-string search
if (mod_file_name == parts[0]) or (mod_file_name in parts[0]):
info.rel_path = parts[0]
info.deps = parts[1].split()
return info
# Not found :(
return None
def copy_module_and_deps(mod_info: ModInfo, src_dir: Path, dst_dir: Path, depth: int = 0) -> None:
# Copy module itself
mod_src_file: Path = src_dir / mod_info.rel_path
mod_dst_file: Path = dst_dir / mod_info.rel_path
os.makedirs(mod_dst_file.parent, exist_ok=True)
if not mod_dst_file.exists():
indent = ' ' + ' ' * depth
print('{}included: {}'.format(indent, mod_info.rel_path))
shutil.copy(mod_src_file, mod_dst_file)
# Recursively copy each dependency and all of its dependencies
for dep_str in mod_info.deps:
dep_info = find_module_and_deps(dep_str, src_dir)
if dep_info is not None:
copy_module_and_deps(dep_info, src_dir, dst_dir, depth + 1)
else:
sys.stderr.write("Can't resolve module dependency: {}".format(dep_str))
# strip any possible file extensions, converting e.g
# "novatek-nvt-ts.ko.zst" => "novatek-nvt-ts"
def strip_all_extensions(fn: str) -> str:
while '.' in fn:
fn = Path(fn).stem
return fn
def main() -> int:
if len(sys.argv) != 4:
print_usage()
sys.exit(1)
mod_name: str = strip_all_extensions(str(sys.argv[1]))
src_dir: Path = Path(sys.argv[2])
dst_dir: Path = Path(sys.argv[3])
built_ins = read_modules_builtin(src_dir)
if mod_name in built_ins:
print(' built-in: {}'.format(mod_name))
return 0
mod_info = find_module_and_deps(mod_name, src_dir)
if mod_info is None:
# test maybe we've got a subdir path passed to us as a parameter?
moddir = src_dir / mod_name
if Path(moddir).is_dir():
print('Including directory: {}'.format(mod_name))
os.makedirs(str(dst_dir), exist_ok=True)
for subpath in moddir.iterdir():
submod = strip_all_extensions(str(subpath))
mod_info = find_module_and_deps(submod, src_dir)
# print(submod, mod_info)
if mod_info:
copy_module_and_deps(mod_info, src_dir, dst_dir)
return 0
sys.stderr.write('Failed to find module: {}\n'.format(mod_name))
return 1
os.makedirs(str(dst_dir), exist_ok=True)
copy_module_and_deps(mod_info, src_dir, dst_dir)
return 0
if __name__ == '__main__':
sys.exit(main())
#!/bin/bash
# LOACLVERSION should be = "" if kernel config has CONFIG_LOCALVERSION set
# otherwise we get version like 6.6.1-sdm660-sdm660
# with `make ... LOCALVERSION="-sdm660"`
SCRIPT_DIR=$( readlink -f $( dirname $0 ) )
echo Kernel build directory: $SCRIPT_DIR
make -C ../ \
ARCH=arm64 \
CROSS_COMPILE=aarch64-linux-gnu- \
O="$SCRIPT_DIR" \
LOCALVERSION= \
-j6 \
$*
#!/bin/bash
./make.sh menuconfig
#!/bin/bash
# set -x
PREFIX=./INSTALL_PREFIX
rm -rf ./${PREFIX}
mkdir -p ${PREFIX}
./make.sh INSTALL_MOD_PATH=${PREFIX} \
INSTALL_MOD_STRIP=1 \
modules_install
echo "Contents of ${PREFIX}/lib/modules:"
ls --color -l ${PREFIX}/lib/modules
# remove symlinks that are... bad
rm -f ${PREFIX}/lib/modules/*/build
rm -f ${PREFIX}/lib/modules/*/source
#!/bin/bash
# Path to dir with results of "make INSTALL_MOD_PATH=${PREFIX} modules_install"
PREFIX=INSTALL_PREFIX
KERNELVERSION=$(ls ${PREFIX}/lib/modules)
# temporary work dir (will be created and removed)
TMP_INITFS_DIR=_initfs
CODENAME=$1
if [[ "x${CODENAME}" = "x" ]]; then
CODENAME="xiaomi-lavender-tianma"
fi
# DEBUG=1
echo "Device codename: ${CODENAME}; Detected kernel version: $KERNELVERSION"
echo "Unpacking original initramfs file: initramfs-${CODENAME}.cpio.gz"
sudo rm -rf ${TMP_INITFS_DIR}
mkdir ${TMP_INITFS_DIR}
cp initramfs-${CODENAME}.cpio.gz ${TMP_INITFS_DIR}
cd ${TMP_INITFS_DIR}
gzip -d initramfs-${CODENAME}.cpio.gz
sudo cpio --quiet -i --file=initramfs-${CODENAME}.cpio
rm -f initramfs-${CODENAME}
cd ..
# debug:
[[ ! -z $DEBUG ]] && echo "Tree before:" && tree ${TMP_INITFS_DIR}
MODULES_SOURCE_DIR=${PREFIX}/lib/modules/${KERNELVERSION}
MODULES_DEST_DIR=${TMP_INITFS_DIR}/lib/modules/${KERNELVERSION}
MODULES_LIST="msm" # qcom display (mdss) + GPU driver (adreno)
MODULES_LIST="${MODULES_LIST} qcom_fg qcom_pmi8998_charger" # battery charger & fuel gauge
# automatically include all panel modules that are built
for modpath in ${MODULES_SOURCE_DIR}/kernel/drivers/gpu/drm/panel/* ; do
modname=$( basename $modpath )
MODULES_LIST="${MODULES_LIST} $modname"
done
# automatically include all touchscreen modules that are built
for modpath in ${MODULES_SOURCE_DIR}/kernel/drivers/input/touchscreen/* ; do
modname=$( basename $modpath )
MODULES_LIST="${MODULES_LIST} $modname"
done
# Read some more default modules into list, form file taken from
# postmarketos-initramfs package (00-default.modules)
while IFS= read -r line
do
MODULES_LIST="${MODULES_LIST} $line"
done < "default-modules.txt"
sudo mkdir -p ${MODULES_DEST_DIR}
# Copy modules.alias, modules.builtin, modules.dep, modules.order and others
sudo cp ${MODULES_SOURCE_DIR}/modules.* ${MODULES_DEST_DIR}/
# Include only needed modules (with all their deps)
for modname in ${MODULES_LIST}; do
sudo python3 ./include_module_in_initfs.py ${modname} ${MODULES_SOURCE_DIR} ${MODULES_DEST_DIR}
done
# DEBUG:
[[ ! -z $DEBUG ]] && echo "Tree after:" && tree ${TMP_INITFS_DIR}
echo "Creating initramfs-${CODENAME}-new.cpio.gz ..."
rm -f initramfs-${CODENAME}-new.cpio.gz
cd ${TMP_INITFS_DIR}
find . | cpio --quiet -o --format=newc | gzip -c -5 > ../initramfs-${CODENAME}-new.cpio.gz
cd ..
sudo rm -r ${TMP_INITFS_DIR}
#echo "==== Results: ===="
ls -la --color initramfs-${CODENAME}*.gz
#!/bin/sh
./make.sh savedefconfig
cp defconfig ../arch/arm64/configs/sdm660_defconfig
git --no-pager diff
#!/bin/sh
HOST=172.16.42.1
if [ -n "$1" ]; then
HOST=$1
fi
KERNVER=$( ls INSTALL_PREFIX/lib/modules )
echo "Uploading modules for ${KERNVER}..."
ssh root@${HOST} "rm -r /lib/modules/${KERNVER}"
scp -r INSTALL_PREFIX/lib/modules/* root@${HOST}:/lib/modules/
echo "Done"
#!/bin/sh
# Requires rsync to be installed on the device
HOST=172.16.42.1
if [ -n "$1" ]; then
HOST=$1
fi
KERNVER=$( ls INSTALL_PREFIX/lib/modules )
echo "Rsyncing modules for ${KERNVER}..."
rsync \
--verbose --archive --update --delete --delete-after --delay-updates \
./INSTALL_PREFIX/lib/modules/${KERNVER}/ \
root@pmos:/lib/modules/${KERNVER}/
#!/bin/bash
while true; do test -e /dev/ttyACM0 && sleep 0.1 && cat /dev/ttyACM0 | grep -vE "^\s?\n$"; done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment