Files
image-builder/tools/partition_table_helper/gptcfg.sh
2025-09-05 15:40:18 +08:00

254 lines
8.0 KiB
Bash
Executable File

#!/usr/bin/env sh
# shellcheck shell=dash disable=SC2034
# TODO: dynamically generate help message
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
partid="$1"; shift 1
new_uuid="${1:-}"
if [ -z "${new_uuid}" ]; then
new_uuid="$(uuidgen)"
fi
logd "Setting new UUID for part ${partid}: ${new_uuid}"
logcmd sgdisk -u "${partid}:${new_uuid}" "${TARGET_FILE}"
}
handle_set_type() {
if [ $# -eq 0 ]; then
loge "part_id not specified."
exit 2
fi
partid="$1"; shift 1
if [ $# -eq 0 ]; then
loge "Type not specified."
exit 2
fi
parttype="$1"; shift 1
if ! printf '%s' "${TYPENAME}" | grep -E "^${parttype}$" > /dev/null; then
loge "Unsupported type: ${parttype}"
exit 2
fi
typecode="$(getvarbyname "TYPECODE_$(str_to_upper "${parttype}")")"
supported_attrs=""
supported_attrs="$(getvarbyname "TYPECODE_$(str_to_upper "${parttype}")_ATTRS:-")"
typeattrbits=""
while [ $# -ne 0 ]; do
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 for part ${partid}: ${typecode}"
logcmd 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 for part ${partid}: ${attrbit}"
logcmd sgdisk -A "${partid}:set:${attrbit}" "${TARGET_FILE}"
done
}
handle_set_name() {
if [ $# -eq 0 ]; then
loge "part_id not specified."
exit 2
fi
partid="$1"; shift 1
if [ $# -eq 0 ]; then
loge "part name not specified."
exit 2
fi
partname="$1"; shift 1
logcmd 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
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 "$@"