forked from OERV-BSP/image-builder
initial
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/build
|
||||
*.kate-swp
|
||||
53
Makefile
Normal file
53
Makefile
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env make
|
||||
|
||||
##### Have default "all" target listed at the beginning
|
||||
.PHONY: default
|
||||
default: all
|
||||
|
||||
define stack_include
|
||||
$$(info Makefile "$$(lastword $$(MAKEFILE_STACK))" includes "$1")
|
||||
MAKEFILE_STACK += $1
|
||||
CURRENT_MAKEFILE := $$(lastword $$(MAKEFILE_STACK))
|
||||
CURRENT_DIR := $$(dir $$(CURRENT_MAKEFILE))
|
||||
include $1
|
||||
MAKEFILE_STACK := $$(wordlist 1,$$(shell expr $$(words $$(MAKEFILE_STACK)) - 1),$$(MAKEFILE_STACK))
|
||||
CURRENT_MAKEFILE := $$(lastword $$(MAKEFILE_STACK))
|
||||
CURRENT_DIR := $$(dir $$(CURRENT_MAKEFILE))
|
||||
endef
|
||||
MAKEFILE_STACK := $(dir .)$(lastword $(MAKEFILE_LIST))
|
||||
CURRENT_MAKEFILE := $(lastword $(MAKEFILE_STACK))
|
||||
CURRENT_DIR := $(dir $(CURRENT_MAKEFILE))
|
||||
|
||||
##### Setup out-of-tree build
|
||||
# ROOT_DIR & WORK_DIR are all absolute path.
|
||||
# As well as DIST_DIR & STAGING_DIR
|
||||
ROOT_DIR := $(realpath .)
|
||||
# O= must be an absolute path, otherwise unexpected behavior will occur when used in combination with make -C
|
||||
ifdef O
|
||||
WORK_DIR := $(realpath $(O))
|
||||
else
|
||||
WORK_DIR := $(ROOT_DIR)/build
|
||||
endif
|
||||
STAGING_DIR := $(WORK_DIR)/staging
|
||||
DIST_DIR := $(WORK_DIR)/dist
|
||||
|
||||
# Collected targets
|
||||
ROOTFS_TARGETS :=
|
||||
BSP_TARGETS :=
|
||||
|
||||
# Makefile function definations
|
||||
$(eval $(call stack_include,$(CURRENT_DIR)functions.mk))
|
||||
|
||||
# Load receipes
|
||||
$(eval $(call stack_include,$(CURRENT_DIR)receipes/receipes.mk))
|
||||
|
||||
.PHONY: all_rootfs
|
||||
all_rootfs: $(ROOTFS_TARGETS)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf "$(WORK_DIR)"
|
||||
|
||||
.PHONY: .test
|
||||
.test:
|
||||
@echo $(MAKEFILE_STACK)
|
||||
111
functions.mk
Normal file
111
functions.mk
Normal file
@@ -0,0 +1,111 @@
|
||||
########
|
||||
dir_guard=@mkdir -p $(@D)
|
||||
|
||||
########
|
||||
define distro_begin
|
||||
ifdef DISTRO_NAME
|
||||
$$(error Distro section "$$(DISTRO_NAME)" is not finished yet)
|
||||
endif
|
||||
DISTRO_NAME := $(1)
|
||||
endef
|
||||
|
||||
########
|
||||
define distro_end
|
||||
ifndef DISTRO_NAME
|
||||
$$(error No paired distro_begin found)
|
||||
endif
|
||||
ifdef RELEASE_NAME
|
||||
$$(error Unfinished distro release "$$(DISTRO_NAME) $$(RELEASE_NAME)" found)
|
||||
endif
|
||||
undefine DISTRO_NAME
|
||||
endef
|
||||
|
||||
########
|
||||
define distro_release_begin
|
||||
ifndef DISTRO_NAME
|
||||
$$(error Not in distro section)
|
||||
endif
|
||||
ifdef RELEASE_NAME
|
||||
$$(error Distro release "$$(DISTRO_NAME) $$(RELEASE_NAME)" is not finished yet)
|
||||
endif
|
||||
RELEASE_NAME := $(1)
|
||||
endef
|
||||
|
||||
########
|
||||
define distro_release_end
|
||||
ifndef RELEASE_NAME
|
||||
$$(error No paired distro_release_begin found)
|
||||
endif
|
||||
undefine RELEASE_NAME
|
||||
endef
|
||||
|
||||
########
|
||||
define add_receipe
|
||||
|
||||
ifndef RELEASE_NAME
|
||||
$$(error Not within distro release section)
|
||||
endif
|
||||
|
||||
# Cleanup and register new receipe
|
||||
undefine RECEIPE_NAME
|
||||
undefine ROOTFS_COMPRESSION
|
||||
undefine EXTENDS
|
||||
include $$(CURRENT_DIR)$1/receipe.mk
|
||||
|
||||
# Check name
|
||||
ifndef RECEIPE_NAME
|
||||
$$(error RECEIPE_NAME not defined)
|
||||
endif
|
||||
# Check compression method
|
||||
ifeq ($$(ROOTFS_COMPRESSION),zstd)
|
||||
ROOTFS_COMPRESSION_SUFFIX := tar.zst
|
||||
ROOTFS_COMPRESSION_CMD := tar --use-compress-program=zstd -cf "$$$$$$$${OUTPUT_ARCHIVE}" -C "$$$$$$$${ROOTFS_DIR}" .
|
||||
else
|
||||
$$(error Unsupported compression mode)
|
||||
endif
|
||||
|
||||
# Define global references
|
||||
$$(DISTRO_NAME)_$$(RELEASE_NAME)_$$(RECEIPE_NAME)_DIR := $$(CURRENT_DIR)$1
|
||||
$$(DISTRO_NAME)_$$(RELEASE_NAME)_$$(RECEIPE_NAME)_ARTIFACT := $(DIST_DIR)/$$(DISTRO_NAME)/$$(RELEASE_NAME)/$$(DISTRO_NAME)-$$(RELEASE_NAME)-$$(RECEIPE_NAME)-rootfs.$$(ROOTFS_COMPRESSION_SUFFIX)
|
||||
ROOTFS_TARGETS += $$(DISTRO_NAME)-$$(RELEASE_NAME)-$$(RECEIPE_NAME)-rootfs
|
||||
|
||||
# Populate workdir
|
||||
# Directory timestamp is not reliable so always resync staging dir
|
||||
.PHONY: $(STAGING_DIR)/$$(DISTRO_NAME)/$$(RELEASE_NAME)/receipes/$$(RECEIPE_NAME)
|
||||
$(STAGING_DIR)/$$(DISTRO_NAME)/$$(RELEASE_NAME)/receipes/$$(RECEIPE_NAME): $$(foreach depname,$$(EXTENDS),$$($$(DISTRO_NAME)_$$(RELEASE_NAME)_$$(depname)_DIR)/) $$(CURRENT_DIR)$1/
|
||||
$$(dir_guard)
|
||||
rm -rf "$$@"
|
||||
@# Not preserving modification time, aka -t
|
||||
rsync -rlpgoD --exclude receipe.mk $$+ $$@
|
||||
|
||||
# Define entry target
|
||||
.PHONY: $$(DISTRO_NAME)-$$(RELEASE_NAME)-$$(RECEIPE_NAME)-rootfs
|
||||
$$(DISTRO_NAME)-$$(RELEASE_NAME)-$$(RECEIPE_NAME)-rootfs: $$($$(DISTRO_NAME)_$$(RELEASE_NAME)_$$(RECEIPE_NAME)_ARTIFACT)
|
||||
define GENERATE_TAR_TARGET
|
||||
$$($$(DISTRO_NAME)_$$(RELEASE_NAME)_$$(RECEIPE_NAME)_ARTIFACT): $(STAGING_DIR)/$$(DISTRO_NAME)/$$(RELEASE_NAME)/receipes/$$(RECEIPE_NAME)
|
||||
$$$$(dir_guard)
|
||||
docker run --rm \
|
||||
-v $(ROOT_DIR)/tools:/image-builder/tools:ro \
|
||||
-v $$$$+:/image-builder/receipe:ro \
|
||||
-v $$$$(dir $$$$@):/image-builder/output \
|
||||
-it docker.io/openeuler/openeuler:24.03-lts \
|
||||
/bin/sh -c ' \
|
||||
mkdir /tmp/rootfs && \
|
||||
cd /image-builder/tools && \
|
||||
./build_rootfs.sh -i /image-builder/receipe -o /tmp/rootfs && \
|
||||
export OUTPUT_ARCHIVE=/image-builder/output/$$$$(notdir $$$$@) && \
|
||||
export ROOTFS_DIR=/tmp/rootfs && \
|
||||
$$(ROOTFS_COMPRESSION_CMD)'
|
||||
endef
|
||||
$$(eval $$(GENERATE_TAR_TARGET))
|
||||
|
||||
|
||||
# Reset registers again
|
||||
undefine GENERATE_TAR_TARGET
|
||||
undefine EXTENDS
|
||||
undefine ROOTFS_COMPRESSION_CMD
|
||||
undefine ROOTFS_COMPRESSION_SUFFIX
|
||||
undefine ROOTFS_COMPRESSION
|
||||
undefine RECEIPE_NAME
|
||||
|
||||
endef
|
||||
@@ -0,0 +1,23 @@
|
||||
DISK_TABLE_TYPE=GUID
|
||||
|
||||
PARTITION_1_OFFSET=1MB
|
||||
PARTITION_1_LENGTH=499MB
|
||||
PARTITION_1_NAME="oerv-boot"
|
||||
PARTITION_1_UUID=
|
||||
PARTITION_1_TYPE=bls_boot
|
||||
PARTITION_1_ATTRS=legacy_boot
|
||||
PARTITION_1_USAGE=MOUNTPOINT
|
||||
PARTITION_1_MOUNTPONT="/boot"
|
||||
PARTITION_1_FILESYSTEM=vfat
|
||||
PARTITION_1_FS_UUID=
|
||||
|
||||
PARTITION_2_OFFSET=
|
||||
PARTITION_2_LENGTH=
|
||||
PARTITION_2_NAME="oerv-root"
|
||||
PARTITION_2_UUID=
|
||||
PARTITION_2_TYPE=linux_root_riscv64
|
||||
PARTITION_2_ATTRS=
|
||||
PARTITION_2_USAGE=MOUNTPOINT
|
||||
PARTITION_2_MOUNTPONT="/"
|
||||
PARTITION_1_FILESYSTEM=ext4
|
||||
PARTITION_1_FS_UUID=
|
||||
@@ -0,0 +1,3 @@
|
||||
firmware-spacemit-k1
|
||||
dracut
|
||||
u-boot-menu
|
||||
@@ -0,0 +1,3 @@
|
||||
# Provide esos.elf for early kernel direct filesystem lookup
|
||||
|
||||
install_items+= /lib/firmware/esos.elf
|
||||
@@ -0,0 +1,6 @@
|
||||
U_BOOT_PROMPT="2"
|
||||
U_BOOT_MENU_LABEL="OpenEuler GNU/Linux, kernel"
|
||||
# tty enabled on both serial0 and fbdev
|
||||
U_BOOT_PARAMETERS="rootwait rw earlycon=sbi console=tty0 console=ttyS0,115200 rd.multipath=0"
|
||||
U_BOOT_ROOT=
|
||||
U_BOOT_FDT_DIR="/dtb-"
|
||||
@@ -0,0 +1,2 @@
|
||||
kernel
|
||||
kernel-headers
|
||||
@@ -0,0 +1,13 @@
|
||||
[bsp-common]
|
||||
name=BSP-Common
|
||||
type=rpm-md
|
||||
baseurl=https://build-repo.tarsier-infra.isrc.ac.cn//home:/salimterryli:/bsp:/common/openeuler-24.03-sp2/
|
||||
enabled=1
|
||||
gpgcheck=0
|
||||
|
||||
[bsp-spacemit-k1]
|
||||
name=BSP-K1
|
||||
type=rpm-md
|
||||
baseurl=https://build-repo.tarsier-infra.isrc.ac.cn//home:/salimterryli:/bsp:/spacemit:/k1/openeuler-24.03-sp2/
|
||||
enabled=1
|
||||
gpgcheck=0
|
||||
8
receipes/openeuler/24.03-lts-sp2/release.mk
Normal file
8
receipes/openeuler/24.03-lts-sp2/release.mk
Normal file
@@ -0,0 +1,8 @@
|
||||
$(eval $(call distro_release_begin,24.03-LTS-SP2))
|
||||
|
||||
$(eval $(call add_receipe,userspace/base))
|
||||
$(eval $(call add_receipe,userspace/xfce4))
|
||||
|
||||
$(foreach mk,$(wildcard $(CURRENT_DIR)bsp/*/board.mk),$(eval $(call stack_include,$(mk))))
|
||||
|
||||
$(eval $(call distro_release_end))
|
||||
@@ -0,0 +1 @@
|
||||
openEuler-repos
|
||||
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env dash
|
||||
|
||||
rm "${ROOTFS_DIR}/etc/yum.repos.d/bootstrap.repo"
|
||||
@@ -0,0 +1 @@
|
||||
base
|
||||
@@ -0,0 +1,2 @@
|
||||
RECEIPE_NAME := base
|
||||
ROOTFS_COMPRESSION := zstd
|
||||
@@ -0,0 +1,10 @@
|
||||
# Temporary repo for openeuler-repos package installation
|
||||
|
||||
[OS]
|
||||
name=OS
|
||||
baseurl=https://mirror.isrc.ac.cn/openeuler/openEuler-24.03-LTS-SP1/OS/$basearch/
|
||||
# metalink=https://mirrors.openeuler.org/metalink?repo=$releasever/OS&arch=$basearch
|
||||
metadata_expire=1h
|
||||
enabled=1
|
||||
gpgcheck=1
|
||||
gpgkey=http://mirror.isrc.ac.cn/openeuler/openEuler-24.03-LTS-SP1/OS/$basearch/RPM-GPG-KEY-openEuler
|
||||
@@ -0,0 +1,8 @@
|
||||
xorg-*
|
||||
xfwm4
|
||||
xfdesktop
|
||||
xfce4-*
|
||||
xfce4-*-plugin
|
||||
lightdm
|
||||
lightdm-gtk
|
||||
linux-firmware
|
||||
@@ -0,0 +1,3 @@
|
||||
RECEIPE_NAME := xfce4
|
||||
ROOTFS_COMPRESSION := zstd
|
||||
EXTENDS := base
|
||||
7
receipes/openeuler/distro.mk
Normal file
7
receipes/openeuler/distro.mk
Normal file
@@ -0,0 +1,7 @@
|
||||
$(eval $(call distro_begin,openEuler))
|
||||
|
||||
PACKAGE_MANAGER := yum
|
||||
|
||||
$(foreach mk,$(wildcard $(CURRENT_DIR)*/release.mk),$(eval $(call stack_include,$(mk))))
|
||||
|
||||
$(eval $(call distro_end))
|
||||
1
receipes/receipes.mk
Normal file
1
receipes/receipes.mk
Normal file
@@ -0,0 +1 @@
|
||||
$(foreach mk,$(wildcard $(CURRENT_DIR)*/distro.mk),$(eval $(call stack_include,$(mk))))
|
||||
66
tools/build_rootfs.sh
Executable file
66
tools/build_rootfs.sh
Executable file
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
|
||||
. ./logging.sh
|
||||
|
||||
RECEIPE_DIR=""
|
||||
ROOTFS_DIR=""
|
||||
|
||||
|
||||
print_usage() {
|
||||
# Keep help message within 80 cols for special consoles.
|
||||
cat << EOF
|
||||
|
||||
Usage: $0 [-hp] [-i input [-i input [...]]] output
|
||||
-h Print this help message.
|
||||
-i receipe Path to directory containing the receipe
|
||||
to make the rootfs.
|
||||
-o rootfs Path to directory that the rootfs will
|
||||
be bootstrapped into.
|
||||
Environment Variables:
|
||||
LOG_LEVEL Controls the log level of this script.
|
||||
One of: DEBUG, INFO, WARN, ERROR
|
||||
Defaults to: INFO
|
||||
EOF
|
||||
}
|
||||
|
||||
main() {
|
||||
# Handling args
|
||||
while getopts "i:o:h" o; do
|
||||
case "${o}" in
|
||||
h)
|
||||
print_usage
|
||||
exit 0
|
||||
;;
|
||||
i)
|
||||
RECEIPE_DIR=${OPTARG}
|
||||
;;
|
||||
o)
|
||||
ROOTFS_DIR=${OPTARG}
|
||||
;;
|
||||
*)
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
# Validate inputs
|
||||
if [ -z "${RECEIPE_DIR}" ]; then
|
||||
loge "No receipe is specified!"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "${ROOTFS_DIR}" ]; then
|
||||
loge "No output dir is specified!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
logi "Using receipe: ${RECEIPE_DIR}"
|
||||
logi "ROOTFS_DIR=${ROOTFS_DIR}"
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
main "$@"
|
||||
254
tools/gptcfg.sh
Executable file
254
tools/gptcfg.sh
Executable file
@@ -0,0 +1,254 @@
|
||||
#!/usr/bin/env dash
|
||||
# shellcheck shell=dash disable=SC2034
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
|
||||
. ./logging.sh
|
||||
|
||||
TARGET_FILE=""
|
||||
|
||||
###################################################
|
||||
|
||||
readonly TYPENAME="
|
||||
efi
|
||||
bls_boot
|
||||
linux_data
|
||||
linux_root_riscv64
|
||||
linux_swap
|
||||
msfdata
|
||||
"
|
||||
|
||||
readonly TYPECODE_EFI="C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
|
||||
readonly TYPECODE_BLS_BOOT="BC13C2FF-59E6-4262-A352-B275FD6F7172"
|
||||
readonly TYPECODE_LINUX_DATA="0FC63DAF-8483-4772-8E79-3D69D8477DE4"
|
||||
readonly TYPECODE_LINUX_ROOT_RISCV64="72EC70A6-CF74-40E6-BD49-4BDA08E8F224"
|
||||
readonly TYPECODE_LINUX_SWAP="0657fd6d-a4ab-43c4-84e5-0933c84b4f4f"
|
||||
readonly TYPECODE_MSFDATA="ebd0a0a2-b9e5-4433-87c0-68b6b72699c7"
|
||||
readonly TYPECODE_MSFRESV="e3c9e316-0b5c-4db8-817d-f92df00215ae"
|
||||
|
||||
readonly TYPECODE_COMMON_ATTRS_LEGACY_BOOT=2
|
||||
readonly TYPECODE_LINUX_ATTRS_NO_AUTO=63
|
||||
readonly TYPECODE_LINUX_ATTRS_RO=60
|
||||
readonly TYPECODE_LINUX_ATTRS_GROWFS=59
|
||||
readonly TYPECODE_MSFDATA_ATTRS_NO_AUTO=63
|
||||
readonly TYPECODE_MSFDATA_ATTRS_RO=60
|
||||
readonly TYPECODE_MSFDATA_HIDDEN=62
|
||||
|
||||
#readonly TYPECODE_EFI_ATTRS=""
|
||||
|
||||
readonly TYPECODE_BLS_BOOT_ATTRS="
|
||||
legacy_boot
|
||||
no_auto
|
||||
ro
|
||||
growfs
|
||||
"
|
||||
readonly TYPECODE_BLS_BOOT_ATTRS_LEGACY_BOOT=$TYPECODE_COMMON_ATTRS_LEGACY_BOOT
|
||||
readonly TYPECODE_BLS_BOOT_ATTRS_NO_AUTO=$TYPECODE_LINUX_ATTRS_NO_AUTO
|
||||
readonly TYPECODE_BLS_BOOT_ATTRS_RO=$TYPECODE_LINUX_ATTRS_RO
|
||||
readonly TYPECODE_BLS_BOOT_ATTRS_GROWFS=$TYPECODE_LINUX_ATTRS_GROWFS
|
||||
|
||||
#readonly TYPECODE_LINUX_DATA_ATTRS=""
|
||||
|
||||
readonly TYPECODE_LINUX_ROOT_RISCV64_ATTRS="
|
||||
legacy_boot
|
||||
no_auto
|
||||
ro
|
||||
growfs
|
||||
"
|
||||
readonly TYPECODE_LINUX_ROOT_RISCV64_ATTRS_LEGACY_BOOT=$TYPECODE_COMMON_ATTRS_LEGACY_BOOT
|
||||
readonly TYPECODE_LINUX_ROOT_RISCV64_ATTRS_NO_AUTO=$TYPECODE_LINUX_ATTRS_NO_AUTO
|
||||
readonly TYPECODE_LINUX_ROOT_RISCV64_ATTRS_RO=$TYPECODE_LINUX_ATTRS_RO
|
||||
readonly TYPECODE_LINUX_ROOT_RISCV64_ATTRS_GROWFS=$TYPECODE_LINUX_ATTRS_GROWFS
|
||||
|
||||
#readonly TYPECODE_LINUX_SWAP_ATTRS=""
|
||||
|
||||
###################################################
|
||||
|
||||
str_to_upper() {
|
||||
printf '%s' "$1" | tr '[:lower:]' '[:upper:]'
|
||||
}
|
||||
|
||||
getvarbyname() {
|
||||
eval printf '%s' \"\$\{"$1"\}\"
|
||||
}
|
||||
|
||||
handle_set_uuid() {
|
||||
if [ $# -eq 0 ]; then
|
||||
loge "part_id not specified."
|
||||
exit 2
|
||||
fi
|
||||
local partid; partid="$1"; shift 1
|
||||
local new_uuid; new_uuid="${1:-}"
|
||||
if [ -z "${new_uuid}" ]; then
|
||||
new_uuid="$(uuidgen)"
|
||||
fi
|
||||
logd "Setting new UUID to part ${partid}: ${new_uuid}"
|
||||
1>/dev/null sgdisk -u "${partid}:${new_uuid}" "${TARGET_FILE}"
|
||||
}
|
||||
|
||||
handle_set_type() {
|
||||
if [ $# -eq 0 ]; then
|
||||
loge "part_id not specified."
|
||||
exit 2
|
||||
fi
|
||||
local partid; partid="$1"; shift 1
|
||||
if [ $# -eq 0 ]; then
|
||||
loge "Type not specified."
|
||||
exit 2
|
||||
fi
|
||||
local parttype; parttype="$1"; shift 1
|
||||
|
||||
if ! printf '%s' "${TYPENAME}" | grep -E "^${parttype}$" > /dev/null; then
|
||||
loge "Unsupported type: ${parttype}"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
local typecode
|
||||
typecode="$(getvarbyname "TYPECODE_$(str_to_upper "${parttype}")")"
|
||||
|
||||
local supported_attrs=""
|
||||
supported_attrs="$(getvarbyname "TYPECODE_$(str_to_upper "${parttype}")_ATTRS:-")"
|
||||
local typeattrbits=""
|
||||
while [ $# -ne 0 ]; do
|
||||
local curr_attr="$1"
|
||||
shift 1
|
||||
if ! printf '%s' "${supported_attrs}" | grep -E "^${curr_attr}$" > /dev/null; then
|
||||
loge "Usupported attribute for type ${parttype}: ${curr_attr}"
|
||||
exit 2
|
||||
fi
|
||||
typeattrbits="${typeattrbits}$(getvarbyname "TYPECODE_$(str_to_upper "${parttype}")_ATTRS_$(str_to_upper "${curr_attr}")")
|
||||
"
|
||||
done
|
||||
logd "Set type code to ${typecode} for part ${partid}"
|
||||
1>/dev/null sgdisk -t "${partid}:${typecode}" "${TARGET_FILE}"
|
||||
printf '%s' "${typeattrbits}" | while read -r attrbit ; do
|
||||
if [ -z "${attrbit}" ]; then
|
||||
continue
|
||||
fi
|
||||
logd "Set partition attribute bit ${attrbit} for part ${partid}"
|
||||
1>/dev/null sgdisk -A "${partid}:set:${attrbit}" "${TARGET_FILE}"
|
||||
done
|
||||
}
|
||||
|
||||
handle_set_name() {
|
||||
if [ $# -eq 0 ]; then
|
||||
loge "part_id not specified."
|
||||
exit 2
|
||||
fi
|
||||
local partid; partid="$1"; shift 1
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
loge "part name not specified."
|
||||
exit 2
|
||||
fi
|
||||
local partname; partname="$1"; shift 1
|
||||
1>/dev/null sgdisk -c "${partid}:${partname}" "${TARGET_FILE}"
|
||||
}
|
||||
|
||||
print_usage() {
|
||||
# Keep help message within 80 cols for special consoles.
|
||||
cat << EOF
|
||||
Configure GUID partition attributes
|
||||
Usage: $0 [-h] target command [parameters]
|
||||
target Path to the disk image file. Can also be a real blockdev.
|
||||
Commands:
|
||||
set-name part_id name
|
||||
Set the GUID partition name.
|
||||
Not to be confused with filesystem label!
|
||||
part_id Partition index, starting from 1.
|
||||
name Name of the partition. Maximum 71 bytes.
|
||||
set-type part_id type [attrs [attrs [...]]]
|
||||
Configure the partition into a pre-defined type.
|
||||
On GUID disks, only one PartitionTypeGUID can be set but
|
||||
multiple Attributes can be applied to the same partition.
|
||||
The supported types are picked from BLS and DPS.
|
||||
Each TypeGUID may support different attrs.
|
||||
part_id Partition index, starting from 1.
|
||||
type Partition usage type. Available options:
|
||||
- efi
|
||||
A standard EFI System Partition. Note that the filesystem
|
||||
still need to be configured by other tools.
|
||||
This type will set:
|
||||
- PartitionTypeGUID: C12A7328-F81F-11D2-BA4B-00A0C93EC93B
|
||||
- bls_boot
|
||||
A Boot Loader Specification compatible partition.
|
||||
Also known as XBOOTLDR. May be auto-mounted by systemd.
|
||||
This type will set:
|
||||
- PartitionTypeGUID: BC13C2FF-59E6-4262-A352-B275FD6F7172
|
||||
Supported attributes:
|
||||
- legacy_boot
|
||||
- no_auto: Do not mount automatically.
|
||||
- ro: Mount as read-only.
|
||||
- growfs: Resize fs to its container size on mounted.
|
||||
- linux_data
|
||||
A normal partition that may hold any of filesystem
|
||||
supported by Linux. No special function.
|
||||
This type will set:
|
||||
- PartitionTypeGUID: 0fc63daf-8483-4772-8e79-3d69d8477de4
|
||||
- linux_root_riscv64
|
||||
A root partition containing riscv64 rootfs. May be auto
|
||||
-mounted by systemd.
|
||||
This type will set:
|
||||
- PartitionTypeGUID: 72ec70a6-cf74-40e6-bd49-4bda08e8f224
|
||||
Supported attributes:
|
||||
- legacy_boot
|
||||
- no_auto: Do not mount automatically.
|
||||
- ro: Mount as read-only.
|
||||
- growfs: Resize fs to its container size on mounted.
|
||||
- linux_swap
|
||||
A swap partition. May be automatically enabled by systemd
|
||||
This type will set:
|
||||
- PartitionTypeGUID: 0657fd6d-a4ab-43c4-84e5-0933c84b4f4f
|
||||
set-uuid part_id [uuid]
|
||||
Set the UniquePartitionGUID.
|
||||
part_id Partition index, starting from 1.
|
||||
uuid UniquePartitionGUID, optional.
|
||||
Leave empty for a random one.
|
||||
EOF
|
||||
}
|
||||
|
||||
main() {
|
||||
while getopts "h" o; do
|
||||
case "${o}" in
|
||||
h)
|
||||
print_usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
if [ "$#" -eq 0 ]; then
|
||||
loge "No target specified."
|
||||
exit 1
|
||||
fi
|
||||
TARGET_FILE="$1"
|
||||
shift 1
|
||||
|
||||
local arg_command
|
||||
if [ "$#" -eq 0 ]; then
|
||||
loge "No command specified."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
arg_command="$1"
|
||||
shift 1
|
||||
if [ "${arg_command}" = "set-name" ]; then
|
||||
handle_set_name "$@"
|
||||
elif [ "${arg_command}" = "set-type" ]; then
|
||||
handle_set_type "$@"
|
||||
elif [ "${arg_command}" = "set-uuid" ]; then
|
||||
handle_set_uuid "$@"
|
||||
else
|
||||
loge "Unrecognized command: ${arg_command}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
main "$@"
|
||||
137
tools/imgcat.sh
Executable file
137
tools/imgcat.sh
Executable file
@@ -0,0 +1,137 @@
|
||||
#!/usr/bin/env dash
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
|
||||
. ./logging.sh
|
||||
|
||||
INPUT_FILES=""
|
||||
OUTPUT_FILE=""
|
||||
ALIGNMENT_SECTOR_SIZE=""
|
||||
ALIGNMENT_SECTOR_COUNT=""
|
||||
ALIGNMENT_BYTES=""
|
||||
|
||||
calc_parts_total_size() {
|
||||
local total_aligned_blocks=0
|
||||
while IFS= read -r line; do
|
||||
if [ -z "${line}" ]; then
|
||||
continue
|
||||
fi
|
||||
ifile_aligned_blocks="$(du --apparent-size -B ${ALIGNMENT_BYTES} "${line}" | cut -f 1)"
|
||||
logi "Input: ${ifile_aligned_blocks} blocks: ${line}"
|
||||
total_aligned_blocks="$((total_aligned_blocks+ifile_aligned_blocks))"
|
||||
done << EOF
|
||||
$INPUT_FILES
|
||||
EOF
|
||||
echo "${total_aligned_blocks}"
|
||||
}
|
||||
|
||||
probe_alignment() {
|
||||
local TEMP_FILE
|
||||
TEMP_FILE="$(mktemp)"
|
||||
truncate -s 1G "${TEMP_FILE}"
|
||||
ALIGNMENT_SECTOR_SIZE="$(sgdisk -p "${TEMP_FILE}" | sed -rn 's/Sector size \(logical\): ([0-9]+) bytes/\1/p')"
|
||||
ALIGNMENT_SECTOR_COUNT="$(sgdisk -p "${TEMP_FILE}" | sed -rn 's/Partitions will be aligned on ([0-9]+)-sector boundaries/\1/p')"
|
||||
ALIGNMENT_BYTES="$((ALIGNMENT_SECTOR_SIZE*ALIGNMENT_SECTOR_COUNT))"
|
||||
rm "${TEMP_FILE}"
|
||||
logd "Probed alignment: ${ALIGNMENT_BYTES}B (${ALIGNMENT_SECTOR_SIZE}B*${ALIGNMENT_SECTOR_COUNT})"
|
||||
}
|
||||
|
||||
print_usage() {
|
||||
# Keep help message within 80 cols for special consoles.
|
||||
cat << EOF
|
||||
Concatenate multiple partitions into a single GUID disk image.
|
||||
This script only handles the image creation.
|
||||
Usage: $0 [-hp] [-i input [-i input [...]]] output
|
||||
-h Print this help message.
|
||||
-p Print the alignment, in bytes
|
||||
-i input Partition images to be included.
|
||||
Multiple inputs are arranged as the specified order.
|
||||
It is recommended to have input file size rounded according
|
||||
to the alignment requirements, as the partition will always
|
||||
be placed at alignment boundaries.
|
||||
output The produced disk image.
|
||||
Environment Variables:
|
||||
LOG_LEVEL Controls the log level of this script.
|
||||
One of: DEBUG, INFO, WARN, ERROR
|
||||
Defaults to: INFO
|
||||
EOF
|
||||
}
|
||||
|
||||
main() {
|
||||
# Handling args
|
||||
while getopts "i:hp" o; do
|
||||
case "${o}" in
|
||||
h)
|
||||
print_usage
|
||||
exit 0
|
||||
;;
|
||||
i)
|
||||
INPUT_FILES="${INPUT_FILES}${OPTARG}
|
||||
"
|
||||
;;
|
||||
p)
|
||||
probe_alignment
|
||||
echo -n "${ALIGNMENT_BYTES}"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
OUTPUT_FILE="${1:-}"
|
||||
|
||||
# Validate inputs
|
||||
if [ -z "${OUTPUT_FILE}" ]; then
|
||||
loge "No output file is specified!"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "${INPUT_FILES}" ]; then
|
||||
loge "No input file is specified!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
probe_alignment
|
||||
logi "Using alignment: ${ALIGNMENT_SECTOR_COUNT} sectors @ ${ALIGNMENT_SECTOR_SIZE}B"
|
||||
|
||||
local target_image_content_size
|
||||
target_image_content_size="$(calc_parts_total_size)"
|
||||
|
||||
# One block is reserved at both beginning and ending, for GPT tables.
|
||||
# Final image size will be target_image_content_size+2 blocks
|
||||
local final_image_blocks="$((target_image_content_size+2))"
|
||||
local final_image_size_b="$((final_image_blocks*ALIGNMENT_BYTES))"
|
||||
logi "Allocating output image (${final_image_blocks} blocks, ${final_image_size_b}B) at ${OUTPUT_FILE}"
|
||||
truncate -s "${final_image_size_b}" "${OUTPUT_FILE}"
|
||||
|
||||
logi "Writing GUID Partition Table"
|
||||
1>/dev/null sgdisk -Z "${OUTPUT_FILE}"
|
||||
1>/dev/null sgdisk -G "${OUTPUT_FILE}"
|
||||
|
||||
local curr_part_idx
|
||||
curr_part_idx=0
|
||||
local curr_part_start_sector
|
||||
curr_part_start_sector="${ALIGNMENT_SECTOR_COUNT}"
|
||||
while IFS= read -r line; do
|
||||
if [ -z "${line}" ]; then
|
||||
continue
|
||||
fi
|
||||
curr_part_idx="$((curr_part_idx+1))"
|
||||
local curr_part_blocks
|
||||
curr_part_blocks="$(du --apparent-size -B "${ALIGNMENT_BYTES}" "${line}" | cut -f 1)"
|
||||
local curr_part_sectors="$((curr_part_blocks*ALIGNMENT_BYTES/ALIGNMENT_SECTOR_SIZE))"
|
||||
logi "Create partition ${curr_part_idx}: ${curr_part_sectors} sectors @ ${curr_part_start_sector} sector"
|
||||
1>/dev/null sgdisk --new "${curr_part_idx}:${curr_part_start_sector}:+${curr_part_sectors}" "${OUTPUT_FILE}"
|
||||
logi "Copy contents to part ${curr_part_idx} from ${line}"
|
||||
2>/dev/null dd if="${line}" of="${OUTPUT_FILE}" bs="${ALIGNMENT_SECTOR_SIZE}" seek="${curr_part_start_sector}" count="${curr_part_sectors}" conv=notrunc iflag=fullblock
|
||||
curr_part_start_sector="$((curr_part_start_sector+curr_part_sectors))"
|
||||
done << EOF
|
||||
$INPUT_FILES
|
||||
EOF
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
main "$@"
|
||||
67
tools/logging.sh
Normal file
67
tools/logging.sh
Normal file
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env false
|
||||
|
||||
readonly LOGLEVEL_DEBUG=0
|
||||
readonly LOGLEVEL_INFO=1
|
||||
readonly LOGLEVEL_WARN=2
|
||||
readonly LOGLEVEL_ERROR=3
|
||||
|
||||
__logparselevel() {
|
||||
if [ -z "${LOG_LEVEL:-}" ]; then
|
||||
echo $LOGLEVEL_INFO
|
||||
elif [ "${LOG_LEVEL}" = "DEBUG" ]; then
|
||||
echo $LOGLEVEL_DEBUG
|
||||
elif [ "${LOG_LEVEL}" = "INFO" ]; then
|
||||
echo $LOGLEVEL_INFO
|
||||
elif [ "${LOG_LEVEL}" = "WARN" ]; then
|
||||
echo $LOGLEVEL_WARN
|
||||
elif [ "${LOG_LEVEL}" = "ERROR" ]; then
|
||||
echo $LOGLEVEL_ERROR
|
||||
else
|
||||
echo $LOGLEVEL_INFO
|
||||
fi
|
||||
}
|
||||
|
||||
__logprintraw() {
|
||||
local formated_msg="$1"
|
||||
>&2 echo "${formated_msg}"
|
||||
}
|
||||
|
||||
__logprint() {
|
||||
local level_fmt="$1"
|
||||
local msg="$2"
|
||||
|
||||
local curr_time; curr_time="[$(date)]"
|
||||
local formated_msg="${curr_time}${level_fmt}: ${msg}"
|
||||
__logprintraw "${formated_msg}"
|
||||
}
|
||||
|
||||
logd() {
|
||||
if [ "$(__logparselevel)" -le "$LOGLEVEL_DEBUG" ]; then
|
||||
__logprint "[DEBUG]" "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
logdraw() {
|
||||
if [ "$(__logparselevel)" -le "$LOGLEVEL_DEBUG" ]; then
|
||||
__logprint "[DEBUG]" "raw print:"
|
||||
__logprintraw "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
logi() {
|
||||
if [ "$(__logparselevel)" -le "$LOGLEVEL_INFO" ]; then
|
||||
__logprint "[INFO ]" "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
logw() {
|
||||
if [ "$(__logparselevel)" -le "$LOGLEVEL_WARN" ]; then
|
||||
__logprint "[WARN ]" "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
loge() {
|
||||
if [ "$(__logparselevel)" -le "$LOGLEVEL_ERROR" ]; then
|
||||
__logprint "[ERROR]" "$1"
|
||||
fi
|
||||
}
|
||||
Reference in New Issue
Block a user