1464 lines
52 KiB
Bash
Executable File
1464 lines
52 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# XOS Partition Configuration Update Script
|
|
# Usage: ./tools/partition/update-partition/update-partition.sh <project_name>
|
|
# Description: Updates partition configuration files based on project-specific config
|
|
|
|
set -e
|
|
|
|
# Color output for better readability
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Print colored output
|
|
print_info() {
|
|
echo -e "${GREEN}[INFO]${NC} $1"
|
|
}
|
|
|
|
print_warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
}
|
|
|
|
print_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
# Check if jq is available for JSON parsing
|
|
check_dependencies() {
|
|
if ! command -v jq &> /dev/null; then
|
|
print_error "jq is required but not installed. Please install jq to parse JSON configuration."
|
|
print_info "Ubuntu/Debian: sudo apt-get install jq"
|
|
print_info "CentOS/RHEL: sudo yum install jq"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Parse command line arguments
|
|
if [ $# -ne 1 ]; then
|
|
print_error "Usage: $0 <project_name>"
|
|
print_info "Example: $0 esl2"
|
|
exit 1
|
|
fi
|
|
|
|
PROJECT_NAME="$1"
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
|
|
CONFIG_FILE="$ROOT_DIR/product/$PROJECT_NAME/partition-config.json"
|
|
|
|
print_info "Starting partition configuration update for project: $PROJECT_NAME"
|
|
print_info "Root directory: $ROOT_DIR"
|
|
|
|
# Verify configuration file exists
|
|
if [ ! -f "$CONFIG_FILE" ]; then
|
|
print_error "Configuration file not found: $CONFIG_FILE"
|
|
print_info "Please create the configuration file first."
|
|
exit 1
|
|
fi
|
|
|
|
print_info "Found configuration file: $CONFIG_FILE"
|
|
|
|
# Parse configuration using jq
|
|
parse_config() {
|
|
local key="$1"
|
|
jq -r ".$key // empty" "$CONFIG_FILE"
|
|
}
|
|
|
|
# Read configuration values
|
|
PROJECT_NAME_CONFIG=$(parse_config "project_name")
|
|
CONFIG_NAME=$(parse_config "config_name")
|
|
PLATFORM=$(parse_config "platform")
|
|
MEDIUM_TYPE=$(parse_config "medium_type")
|
|
MEDIUM_SIZE=$(parse_config "medium_size")
|
|
OS_TYPE=$(parse_config "os_type")
|
|
|
|
# Validate required fields
|
|
validate_config() {
|
|
local errors=0
|
|
|
|
if [ -z "$PROJECT_NAME_CONFIG" ]; then
|
|
print_error "Missing required field: project_name"
|
|
((errors++))
|
|
fi
|
|
|
|
if [ -z "$CONFIG_NAME" ]; then
|
|
print_error "Missing required field: config_name"
|
|
((errors++))
|
|
fi
|
|
|
|
if [ -z "$PLATFORM" ]; then
|
|
print_error "Missing required field: platform"
|
|
((errors++))
|
|
elif [[ ! "$PLATFORM" =~ ^(qm10xd|qm10xv|qm10xh)$ ]]; then
|
|
print_error "Invalid platform: $PLATFORM (must be qm10xd, qm10xv, or qm10xh)"
|
|
((errors++))
|
|
fi
|
|
|
|
if [ -z "$MEDIUM_TYPE" ]; then
|
|
print_error "Missing required field: medium_type"
|
|
((errors++))
|
|
elif [[ ! "$MEDIUM_TYPE" =~ ^(los_spi-nand|los_spi-nor|los_emmc)$ ]]; then
|
|
print_error "Invalid medium_type: $MEDIUM_TYPE (must be los_spi-nand, los_spi-nor, or los_emmc)"
|
|
((errors++))
|
|
fi
|
|
|
|
if [ -z "$OS_TYPE" ]; then
|
|
print_error "Missing required field: os_type"
|
|
((errors++))
|
|
elif [[ ! "$OS_TYPE" =~ ^(linux|rtt|linuxrttv2)$ ]]; then
|
|
print_error "Invalid os_type: $OS_TYPE (must be linux or rtt)"
|
|
((errors++))
|
|
fi
|
|
|
|
if [ $errors -gt 0 ]; then
|
|
print_error "Configuration validation failed with $errors errors"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Convert size based on filesystem type
|
|
convert_partition_size() {
|
|
local size="$1"
|
|
local fs_type="$2"
|
|
|
|
# Extract numeric value and unit
|
|
local numeric=$(echo "$size" | sed 's/[^0-9.]//g')
|
|
local unit=$(echo "$size" | sed 's/[0-9.]//g' | tr '[:lower:]' '[:upper:]')
|
|
|
|
# Convert to bytes for ubi, jffs2, squashfs
|
|
case "$fs_type" in
|
|
"ubi"|"jffs2"|"squashfs")
|
|
case "$unit" in
|
|
"MB"|"M")
|
|
echo $((${numeric%.*} * 1024 * 1024))
|
|
;;
|
|
"KB"|"K")
|
|
echo $((${numeric%.*} * 1024))
|
|
;;
|
|
"GB"|"G")
|
|
echo $((${numeric%.*} * 1024 * 1024 * 1024))
|
|
;;
|
|
*)
|
|
# If no unit, assume it's already in bytes
|
|
echo "$numeric"
|
|
;;
|
|
esac
|
|
;;
|
|
"ext4")
|
|
# Keep original format for ext4
|
|
case "$unit" in
|
|
"MB"|"M")
|
|
echo "${numeric%.*}"
|
|
;;
|
|
"KB"|"K")
|
|
echo $((${numeric%.*} / 1024))
|
|
;;
|
|
"GB"|"G")
|
|
echo $((${numeric%.*} * 1024))
|
|
;;
|
|
*)
|
|
echo "$numeric"
|
|
;;
|
|
esac
|
|
;;
|
|
"raw"|*)
|
|
# For raw partitions, keep original format in MB
|
|
case "$unit" in
|
|
"MB"|"M")
|
|
echo "${numeric%.*}"
|
|
;;
|
|
"KB"|"K")
|
|
echo $((${numeric%.*} / 1024))
|
|
;;
|
|
"GB"|"G")
|
|
echo $((${numeric%.*} * 1024))
|
|
;;
|
|
*)
|
|
echo "$numeric"
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Generate partition-info.txt content
|
|
generate_partition_info() {
|
|
local partition_info_file="$ROOT_DIR/product/$PROJECT_NAME/partition-info.txt"
|
|
|
|
print_info "Generating partition-info.txt: $partition_info_file"
|
|
|
|
# Create product directory if it doesn't exist
|
|
mkdir -p "$(dirname "$partition_info_file")"
|
|
|
|
# Check if partition-info.txt already exists
|
|
if [ -f "$partition_info_file" ]; then
|
|
# Backup original file and preserve permissions
|
|
cp -p "$partition_info_file" "${partition_info_file}.backup"
|
|
|
|
# Store original file permissions
|
|
local original_perms=$(stat -c "%a" "$partition_info_file" 2>/dev/null || echo "644")
|
|
|
|
# Create temporary file for processing
|
|
local temp_file="${partition_info_file}.tmp"
|
|
> "$temp_file"
|
|
|
|
# Process existing file line by line
|
|
while IFS=',' read -r part_name part_fs part_size || [ -n "$part_name" ]; do
|
|
# Strip carriage returns from all fields
|
|
part_name=$(echo "$part_name" | tr -d '\r')
|
|
part_fs=$(echo "$part_fs" | tr -d '\r')
|
|
part_size=$(echo "$part_size" | tr -d '\r')
|
|
|
|
# Skip empty lines and terminator
|
|
if [ -z "$part_name" ] || [ "$part_name" = "::" ]; then
|
|
if [ "$part_name" = "::" ]; then
|
|
echo "::" >> "$temp_file"
|
|
fi
|
|
continue
|
|
fi
|
|
|
|
# Check if this partition exists in JSON config
|
|
local json_partition=$(jq -c --arg name "$part_name" '.partition_table[] | select(.name == $name)' "$CONFIG_FILE")
|
|
|
|
if [ -n "$json_partition" ]; then
|
|
# Partition exists in JSON, process it
|
|
local size=$(echo "$json_partition" | jq -r '.size')
|
|
local fs_type=$(echo "$json_partition" | jq -r '.filesystem_type // "raw"')
|
|
|
|
# Only update if filesystem type matches target types (ubi, jffs2, squashfs, ext4)
|
|
if [[ "$fs_type" =~ ^(ubi|jffs2|squashfs|ext4)$ ]]; then
|
|
# Convert size based on filesystem type
|
|
local converted_size=""
|
|
case "$fs_type" in
|
|
"ubi"|"jffs2"|"squashfs")
|
|
# Convert to bytes
|
|
converted_size=$(convert_partition_size "$size" "$fs_type")
|
|
;;
|
|
"ext4")
|
|
# Keep MB format for ext4
|
|
local numeric=$(echo "$size" | sed 's/[^0-9.]//g')
|
|
local unit=$(echo "$size" | sed 's/[0-9.]//g' | tr '[:lower:]' '[:upper:]')
|
|
case "$unit" in
|
|
"MB"|"M")
|
|
converted_size="${numeric%.*}"
|
|
;;
|
|
"KB"|"K")
|
|
converted_size=$((${numeric%.*} / 1024))
|
|
;;
|
|
"GB"|"G")
|
|
converted_size=$((${numeric%.*} * 1024))
|
|
;;
|
|
*)
|
|
converted_size="$numeric"
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|
|
|
|
echo "${part_name},${fs_type},${converted_size}" | tr -d '\r' >> "$temp_file"
|
|
else
|
|
# Keep original line for non-target filesystem types
|
|
echo "${part_name},${part_fs},${part_size}" | tr -d '\r' >> "$temp_file"
|
|
fi
|
|
else
|
|
# Partition not found in JSON, keep original line
|
|
echo "${part_name},${part_fs},${part_size}" | tr -d '\r' >> "$temp_file"
|
|
fi
|
|
done < "$partition_info_file"
|
|
|
|
# Replace original with updated file and preserve permissions
|
|
chmod "$original_perms" "$temp_file" 2>/dev/null || true
|
|
mv "$temp_file" "$partition_info_file"
|
|
else
|
|
# File doesn't exist, create new one with all partitions
|
|
> "$partition_info_file"
|
|
|
|
# Process each partition from JSON
|
|
while IFS= read -r partition_json; do
|
|
local name=$(echo "$partition_json" | jq -r '.name')
|
|
local size=$(echo "$partition_json" | jq -r '.size')
|
|
local fs_type=$(echo "$partition_json" | jq -r '.filesystem_type // "raw"')
|
|
|
|
# Convert size based on filesystem type
|
|
local converted_size=""
|
|
case "$fs_type" in
|
|
"ubi"|"jffs2"|"squashfs")
|
|
converted_size=$(convert_partition_size "$size" "$fs_type")
|
|
;;
|
|
"ext4")
|
|
local numeric=$(echo "$size" | sed 's/[^0-9.]//g')
|
|
local unit=$(echo "$size" | sed 's/[0-9.]//g' | tr '[:lower:]' '[:upper:]')
|
|
case "$unit" in
|
|
"MB"|"M")
|
|
converted_size="${numeric%.*}"
|
|
;;
|
|
"KB"|"K")
|
|
converted_size=$((${numeric%.*} / 1024))
|
|
;;
|
|
"GB"|"G")
|
|
converted_size=$((${numeric%.*} * 1024))
|
|
;;
|
|
*)
|
|
converted_size="$numeric"
|
|
;;
|
|
esac
|
|
;;
|
|
"raw"|*)
|
|
local numeric=$(echo "$size" | sed 's/[^0-9.]//g')
|
|
local unit=$(echo "$size" | sed 's/[0-9.]//g' | tr '[:lower:]' '[:upper:]')
|
|
case "$unit" in
|
|
"MB"|"M")
|
|
converted_size="${numeric%.*}"
|
|
;;
|
|
"KB"|"K")
|
|
converted_size=$((${numeric%.*} / 1024))
|
|
;;
|
|
"GB"|"G")
|
|
converted_size=$((${numeric%.*} * 1024))
|
|
;;
|
|
*)
|
|
converted_size="$numeric"
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|
|
|
|
echo "${name},${fs_type},${converted_size}" | tr -d '\r' >> "$partition_info_file"
|
|
done < <(jq -c '.partition_table[]' "$CONFIG_FILE")
|
|
|
|
# Add terminator
|
|
echo "::" >> "$partition_info_file"
|
|
fi
|
|
|
|
print_info "Generated partition-info.txt successfully with selective filesystem-aware size conversion (permissions preserved)"
|
|
}
|
|
|
|
# Convert size strings like "18MB", "128KB" to hex values
|
|
convert_size_to_hex() {
|
|
local size="$1"
|
|
|
|
# Extract numeric value and unit
|
|
local numeric=$(echo "$size" | sed 's/[^0-9.]//g')
|
|
local unit=$(echo "$size" | sed 's/[0-9.]//g' | tr '[:lower:]' '[:upper:]')
|
|
|
|
# Convert to bytes then to hex
|
|
case "$unit" in
|
|
"MB"|"M")
|
|
printf "0x%x" $((${numeric%.*} * 1024 * 1024))
|
|
;;
|
|
"KB"|"K")
|
|
printf "0x%x" $((${numeric%.*} * 1024))
|
|
;;
|
|
"GB"|"G")
|
|
printf "0x%x" $((${numeric%.*} * 1024 * 1024 * 1024))
|
|
;;
|
|
*)
|
|
# If no unit, assume it's already in bytes
|
|
printf "0x%x" "${numeric%.*}"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Format hex values with size/offset conversion rules
|
|
format_size_offset() {
|
|
local hex_value="$1"
|
|
local is_size="$2" # true for size, false for offset
|
|
|
|
# Convert hex to decimal
|
|
local decimal_value=$((hex_value))
|
|
|
|
# Special case for offset=0: return "0" directly
|
|
if [ "$is_size" = "false" ] && [ "$decimal_value" -eq 0 ]; then
|
|
echo "0"
|
|
return
|
|
fi
|
|
|
|
# Apply conversion rules
|
|
if [ $((decimal_value % 0x100000)) -eq 0 ]; then
|
|
# Divisible by 1MB (0x100000)
|
|
echo "$((decimal_value / 0x100000))m"
|
|
elif [ $((decimal_value % 0x400)) -eq 0 ]; then
|
|
# Divisible by 1KB (0x400)
|
|
echo "$((decimal_value / 0x400))k"
|
|
else
|
|
# Keep hex format
|
|
echo "$hex_value"
|
|
fi
|
|
}
|
|
|
|
# Extract UBI partition entries from script.ini
|
|
extract_ubi_partitions() {
|
|
local script_file="$1"
|
|
|
|
if [ ! -f "$script_file" ]; then
|
|
return 1
|
|
fi
|
|
|
|
# Find lines containing .ubi files and extract partition names and sizes
|
|
grep -E '\.(ubi|ubi\.lzma)' "$script_file" | while read -r line; do
|
|
# Extract the .ubi filename pattern: name_pagesize_blocksize_size.ubi
|
|
local ubi_file=$(echo "$line" | grep -oE '[a-zA-Z0-9_-]+_[0-9]+[KM]B_[0-9]+[KM]B_[0-9]+[MG]B\.(ubi|ubi\.lzma)')
|
|
if [ -n "$ubi_file" ]; then
|
|
# Extract partition name (everything before first underscore after removing .ubi)
|
|
local partition_name=$(echo "$ubi_file" | sed 's/_[0-9].*\.ubi.*$//' | sed 's/\.ubi.*$//')
|
|
echo "$partition_name:$ubi_file"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Extract mtdparts string from script.ini
|
|
extract_mtdparts_string() {
|
|
local script_file="$1"
|
|
|
|
if [ ! -f "$script_file" ]; then
|
|
return 1
|
|
fi
|
|
|
|
# Find mtdparts string enclosed in single quotes
|
|
local mtdparts_line=$(grep -E "mtdparts=" "$script_file" | head -1)
|
|
if [ -n "$mtdparts_line" ]; then
|
|
# Extract device name and partition info
|
|
local device_name=$(echo "$mtdparts_line" | sed -n "s/.*mtdparts=\([^:]*\):.*/\1/p")
|
|
echo "$device_name"
|
|
fi
|
|
}
|
|
|
|
# Generate mtdparts string from partition_table
|
|
generate_mtdparts_string() {
|
|
local device_name="$1"
|
|
|
|
if [ -z "$device_name" ]; then
|
|
device_name="spi_nfc" # Default device name
|
|
fi
|
|
|
|
# Read partition_table from CONFIG_FILE using jq
|
|
local partition_count=$(jq '.partition_table | length' "$CONFIG_FILE")
|
|
local mtdparts_entries=""
|
|
|
|
for ((i=0; i<partition_count; i++)); do
|
|
local name=$(jq -r ".partition_table[$i].name" "$CONFIG_FILE")
|
|
local size=$(jq -r ".partition_table[$i].size" "$CONFIG_FILE")
|
|
local offset=$(jq -r ".partition_table[$i].offset" "$CONFIG_FILE")
|
|
|
|
# Convert size and offset to appropriate format
|
|
local size_hex=$(convert_size_to_hex "$size")
|
|
local offset_hex="$offset"
|
|
|
|
# Format size and offset
|
|
local formatted_size=$(format_size_offset "$size_hex" "true")
|
|
local formatted_offset=$(format_size_offset "$offset_hex" "false")
|
|
|
|
# For the last partition, use '-' for size
|
|
if [ $i -eq $((partition_count - 1)) ]; then
|
|
formatted_size="-"
|
|
fi
|
|
|
|
# Build mtdparts entry: size@offset(name)
|
|
local entry="${formatted_size}@${formatted_offset}(${name})"
|
|
|
|
if [ -z "$mtdparts_entries" ]; then
|
|
mtdparts_entries="$entry"
|
|
else
|
|
mtdparts_entries="${mtdparts_entries},${entry}"
|
|
fi
|
|
done
|
|
|
|
echo "mtdparts=${device_name}:${mtdparts_entries}"
|
|
}
|
|
|
|
# Generate mtdparts string for CONFIG_MTDPARTS_DEFAULT (with offsets)
|
|
generate_mtdparts_default_string() {
|
|
local device_name="$1"
|
|
|
|
if [ -z "$device_name" ]; then
|
|
device_name="spi_nfc" # Default device name
|
|
fi
|
|
|
|
# Read partition_table from CONFIG_FILE using jq
|
|
local partition_count=$(jq '.partition_table | length' "$CONFIG_FILE")
|
|
local mtdparts_entries=""
|
|
|
|
for ((i=0; i<partition_count; i++)); do
|
|
local name=$(jq -r ".partition_table[$i].name" "$CONFIG_FILE")
|
|
local size=$(jq -r ".partition_table[$i].size" "$CONFIG_FILE")
|
|
local offset=$(jq -r ".partition_table[$i].offset" "$CONFIG_FILE")
|
|
|
|
# Convert size and offset to appropriate format
|
|
local size_hex=$(convert_size_to_hex "$size")
|
|
local offset_hex="$offset"
|
|
|
|
# Format size and offset
|
|
local formatted_size=$(format_size_offset "$size_hex" "true")
|
|
local formatted_offset=$(format_size_offset "$offset_hex" "false")
|
|
|
|
# For the last partition, use '-' for size
|
|
if [ $i -eq $((partition_count - 1)) ]; then
|
|
formatted_size="-"
|
|
fi
|
|
|
|
# Build mtdparts entry: size@offset(name)
|
|
local entry="${formatted_size}@${formatted_offset}(${name})"
|
|
|
|
if [ -z "$mtdparts_entries" ]; then
|
|
mtdparts_entries="$entry"
|
|
else
|
|
mtdparts_entries="${mtdparts_entries},${entry}"
|
|
fi
|
|
done
|
|
|
|
echo "mtdparts=${device_name}:${mtdparts_entries}"
|
|
}
|
|
|
|
# Extract device name from existing defconfig
|
|
extract_device_name_from_defconfig() {
|
|
local defconfig_file="$1"
|
|
local device_name=""
|
|
|
|
if [ -f "$defconfig_file" ]; then
|
|
# Extract from CONFIG_BOOTARGS mtdparts
|
|
device_name=$(grep "^CONFIG_BOOTARGS=" "$defconfig_file" | sed -n 's/.*mtdparts=\([^:]*\):.*/\1/p')
|
|
|
|
# Fallback: Extract from CONFIG_MTDPARTS_DEFAULT
|
|
if [ -z "$device_name" ]; then
|
|
device_name=$(grep "^CONFIG_MTDPARTS_DEFAULT=" "$defconfig_file" | sed -n 's/.*mtdparts=\([^:]*\):.*/\1/p')
|
|
fi
|
|
fi
|
|
|
|
# Default fallback
|
|
if [ -z "$device_name" ]; then
|
|
device_name="spi_nfc"
|
|
fi
|
|
|
|
echo "$device_name"
|
|
}
|
|
|
|
# Update mtdparts portion within CONFIG_BOOTARGS while preserving other parameters
|
|
update_bootargs_mtdparts() {
|
|
local defconfig_file="$1"
|
|
local new_mtdparts="$2"
|
|
local temp_file="$3"
|
|
|
|
# Check if CONFIG_BOOTARGS exists
|
|
if grep -q "^CONFIG_BOOTARGS=" "$defconfig_file"; then
|
|
# Extract device name from existing mtdparts in bootargs
|
|
local existing_device=$(grep "^CONFIG_BOOTARGS=" "$defconfig_file" | sed -n 's/.*mtdparts=\([^:]*\):.*/\1/p')
|
|
|
|
if [ -n "$existing_device" ]; then
|
|
# Replace only the partition definitions after device:, keeping the device name
|
|
local device_mtdparts="mtdparts=${existing_device}:${new_mtdparts#*:}"
|
|
sed -i "s|mtdparts=[^\"']*|${device_mtdparts}|g" "$temp_file"
|
|
print_info "Updated CONFIG_BOOTARGS mtdparts for device: $existing_device"
|
|
else
|
|
# No existing mtdparts found, use the complete new_mtdparts
|
|
sed -i "s|mtdparts=[^\"']*|${new_mtdparts}|g" "$temp_file"
|
|
print_info "Added new CONFIG_BOOTARGS mtdparts"
|
|
fi
|
|
else
|
|
print_warning "No CONFIG_BOOTARGS found in defconfig"
|
|
fi
|
|
}
|
|
|
|
# Update or add CONFIG_MTDPARTS_DEFAULT line
|
|
update_mtdparts_default() {
|
|
local defconfig_file="$1"
|
|
local new_mtdparts="$2"
|
|
local temp_file="$3"
|
|
|
|
# Check if CONFIG_MTDPARTS_DEFAULT exists
|
|
if grep -q "^CONFIG_MTDPARTS_DEFAULT=" "$defconfig_file"; then
|
|
# Replace existing line
|
|
sed -i "s|^CONFIG_MTDPARTS_DEFAULT=.*|CONFIG_MTDPARTS_DEFAULT=\"${new_mtdparts}\"|" "$temp_file"
|
|
print_info "Updated existing CONFIG_MTDPARTS_DEFAULT"
|
|
else
|
|
# Add new line after CONFIG_MTDIDS_DEFAULT or at appropriate location
|
|
if grep -q "^CONFIG_MTDIDS_DEFAULT=" "$defconfig_file"; then
|
|
sed -i "/^CONFIG_MTDIDS_DEFAULT=/a CONFIG_MTDPARTS_DEFAULT=\"${new_mtdparts}\"" "$temp_file"
|
|
else
|
|
# Add after CONFIG_CMD_MTDPARTS if it exists
|
|
if grep -q "^CONFIG_CMD_MTDPARTS=" "$defconfig_file"; then
|
|
sed -i "/^CONFIG_CMD_MTDPARTS=/a CONFIG_MTDPARTS_DEFAULT=\"${new_mtdparts}\"" "$temp_file"
|
|
else
|
|
# Add at end of file
|
|
echo "CONFIG_MTDPARTS_DEFAULT=\"${new_mtdparts}\"" >> "$temp_file"
|
|
fi
|
|
fi
|
|
print_info "Added new CONFIG_MTDPARTS_DEFAULT"
|
|
fi
|
|
}
|
|
|
|
# Validate the updated defconfig contains proper mtdparts
|
|
validate_defconfig_update() {
|
|
local defconfig_file="$1"
|
|
local expected_mtdparts="$2"
|
|
|
|
# Check if CONFIG_BOOTARGS contains the mtdparts
|
|
local bootargs_mtdparts=$(grep "^CONFIG_BOOTARGS=" "$defconfig_file" | grep -o 'mtdparts=[^"]*')
|
|
|
|
# Check if CONFIG_MTDPARTS_DEFAULT exists
|
|
local mtdparts_default=$(grep "^CONFIG_MTDPARTS_DEFAULT=" "$defconfig_file")
|
|
|
|
if [ -n "$bootargs_mtdparts" ] || [ -n "$mtdparts_default" ]; then
|
|
print_info "Validation successful: mtdparts configuration found in defconfig"
|
|
return 0
|
|
else
|
|
print_error "Validation failed: mtdparts configuration not properly updated"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Update mtdparts portion within CONFIG_BOOTARGS in header file
|
|
update_header_bootargs() {
|
|
local header_file="$1"
|
|
local new_mtdparts_str="$2"
|
|
local temp_file="$3"
|
|
local device_name="$4"
|
|
|
|
# Check if CONFIG_BOOTARGS exists
|
|
if grep -q "^#define CONFIG_BOOTARGS" "$header_file"; then
|
|
# Check if mtdparts exists in CONFIG_BOOTARGS
|
|
if grep "^#define CONFIG_BOOTARGS" "$header_file" | grep -q "mtdparts="; then
|
|
# Delete content after mtdparts=device_name: until the closing quote, then add new content
|
|
# This handles both single-line and multi-line definitions
|
|
sed -i '/^#define CONFIG_BOOTARGS/,/[^\\]$/{
|
|
s|mtdparts=[^:]*:[^"]*"|mtdparts='"${device_name}"':'"${new_mtdparts_str}"'"|g
|
|
}' "$temp_file"
|
|
print_info "Updated mtdparts in CONFIG_BOOTARGS"
|
|
else
|
|
# No mtdparts found, add it before the closing quote
|
|
# Remove trailing quote and backslashes, add mtdparts, then add quote back
|
|
sed -i '/^#define CONFIG_BOOTARGS/,/[^\\]$/{
|
|
s|"[[:space:]]*$| mtdparts='"${device_name}"':'"${new_mtdparts_str}"'"|
|
|
}' "$temp_file"
|
|
print_info "Added mtdparts to CONFIG_BOOTARGS"
|
|
fi
|
|
else
|
|
print_warning "No CONFIG_BOOTARGS found in header file"
|
|
fi
|
|
}
|
|
|
|
# Update MTDPARTS_DEFAULT in header file
|
|
update_header_mtdparts_default() {
|
|
local header_file="$1"
|
|
local new_mtdparts_str="$2"
|
|
local temp_file="$3"
|
|
local device_name="$4"
|
|
|
|
# Check if MTDPARTS_DEFAULT exists
|
|
if grep -q "^#define MTDPARTS_DEFAULT" "$header_file"; then
|
|
# Check if mtdparts exists in MTDPARTS_DEFAULT
|
|
if grep "^#define MTDPARTS_DEFAULT" "$header_file" | grep -q "mtdparts="; then
|
|
# Delete content after mtdparts=device_name: until the closing quote, then add new content
|
|
# This handles both single-line and multi-line definitions
|
|
sed -i '/^#define MTDPARTS_DEFAULT/,/[^\\]$/{
|
|
s|mtdparts=[^:]*:[^"]*"|mtdparts='"${device_name}"':'"${new_mtdparts_str}"'"|g
|
|
}' "$temp_file"
|
|
print_info "Updated mtdparts in MTDPARTS_DEFAULT"
|
|
else
|
|
# No mtdparts found, add it before the closing quote
|
|
sed -i '/^#define MTDPARTS_DEFAULT/,/[^\\]$/{
|
|
s|"[[:space:]]*$|mtdparts='"${device_name}"':'"${new_mtdparts_str}"'"|
|
|
}' "$temp_file"
|
|
print_info "Added mtdparts to MTDPARTS_DEFAULT"
|
|
fi
|
|
else
|
|
# Add new MTDPARTS_DEFAULT line if it doesn't exist
|
|
echo "#define MTDPARTS_DEFAULT \"mtdparts=${device_name}:${new_mtdparts_str}\"" >> "$temp_file"
|
|
print_info "Added new MTDPARTS_DEFAULT"
|
|
fi
|
|
}
|
|
|
|
# Update defconfig based on platform
|
|
update_defconfig() {
|
|
# Skip defconfig processing for los_emmc medium type
|
|
if [ "$MEDIUM_TYPE" = "los_emmc" ]; then
|
|
print_info "Skipping defconfig update for los_emmc medium type"
|
|
return 0
|
|
fi
|
|
|
|
# Skip defconfig processing for non-qm10xd platforms
|
|
if [ "$PLATFORM" = "qm10xv" ]; then
|
|
print_info "Skipping defconfig update for platform: $PLATFORM (only qm10xv qm10xh supported)"
|
|
return 0
|
|
fi
|
|
|
|
local defconfig_file=""
|
|
|
|
case "$PLATFORM" in
|
|
"qm10xd")
|
|
defconfig_file="$ROOT_DIR/base/soc/qm10xd/$OS_TYPE/bsp/uboot/uboot/configs/quaming_qm10xd_${CONFIG_NAME}_defconfig"
|
|
;;
|
|
"qm10xv")
|
|
defconfig_file="$ROOT_DIR/base/soc/qm10xv/$OS_TYPE/board_support/uboot/uboot/configs/qua_10xv_${CONFIG_NAME}_defconfig"
|
|
;;
|
|
"qm10xh")
|
|
defconfig_file="$ROOT_DIR/base/soc/qm10xh/$OS_TYPE/bsp/uboot/uboot/configs/quaming_qm108h_${CONFIG_NAME}_defconfig"
|
|
;;
|
|
*)
|
|
print_error "Unsupported platform: $PLATFORM"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
print_info "Updating defconfig: $defconfig_file"
|
|
|
|
# Validate defconfig file exists
|
|
if [ ! -f "$defconfig_file" ]; then
|
|
print_error "Defconfig file not found: $defconfig_file"
|
|
print_info "Cannot update non-existent defconfig file"
|
|
return 1
|
|
fi
|
|
|
|
# Validate JSON configuration exists and contains partition_table
|
|
if [ ! -f "$CONFIG_FILE" ]; then
|
|
print_error "Configuration file not found: $CONFIG_FILE"
|
|
return 1
|
|
fi
|
|
|
|
local partition_count=$(jq '.partition_table | length' "$CONFIG_FILE" 2>/dev/null)
|
|
if [ -z "$partition_count" ] || [ "$partition_count" -eq 0 ]; then
|
|
print_error "No valid partition_table found in configuration file"
|
|
return 1
|
|
fi
|
|
|
|
# Create backup
|
|
local backup_file="${defconfig_file}.backup"
|
|
cp "$defconfig_file" "$backup_file"
|
|
print_info "Created backup: $backup_file"
|
|
|
|
# Extract device name from existing defconfig
|
|
local device_name=$(extract_device_name_from_defconfig "$defconfig_file")
|
|
print_info "Detected MTD device name: $device_name"
|
|
|
|
# Generate new mtdparts string using existing function (for CONFIG_BOOTARGS)
|
|
local new_mtdparts=$(generate_mtdparts_string "$device_name")
|
|
if [ -z "$new_mtdparts" ]; then
|
|
print_error "Failed to generate mtdparts string"
|
|
return 1
|
|
fi
|
|
print_info "Generated mtdparts for CONFIG_BOOTARGS: $new_mtdparts"
|
|
|
|
# Generate mtdparts string for CONFIG_MTDPARTS_DEFAULT (without offsets)
|
|
local new_mtdparts_default=$(generate_mtdparts_default_string "$device_name")
|
|
if [ -z "$new_mtdparts_default" ]; then
|
|
print_error "Failed to generate mtdparts default string"
|
|
return 1
|
|
fi
|
|
print_info "Generated mtdparts for CONFIG_MTDPARTS_DEFAULT: $new_mtdparts_default"
|
|
|
|
# Create temporary file for processing
|
|
local temp_file=$(mktemp)
|
|
cp "$defconfig_file" "$temp_file"
|
|
|
|
# Update CONFIG_BOOTARGS mtdparts portion
|
|
update_bootargs_mtdparts "$defconfig_file" "$new_mtdparts" "$temp_file"
|
|
|
|
# Update CONFIG_MTDPARTS_DEFAULT
|
|
update_mtdparts_default "$defconfig_file" "$new_mtdparts_default" "$temp_file"
|
|
|
|
# Replace original file and preserve permissions
|
|
chmod --reference="$defconfig_file" "$temp_file" 2>/dev/null || true
|
|
mv "$temp_file" "$defconfig_file"
|
|
|
|
# Validate the update
|
|
validate_defconfig_update "$defconfig_file" "$new_mtdparts"
|
|
local validation_result=$?
|
|
|
|
if [ $validation_result -eq 0 ]; then
|
|
print_info "Updated defconfig successfully with mtdparts configuration"
|
|
else
|
|
print_warning "Defconfig updated but validation failed - please verify manually"
|
|
fi
|
|
|
|
return $validation_result
|
|
}
|
|
|
|
# Convert size strings like "18MB", "128KB" to bytes for DTS format
|
|
convert_size_to_bytes() {
|
|
local size="$1"
|
|
|
|
# Extract numeric value and unit
|
|
local numeric=$(echo "$size" | sed 's/[^0-9.]//g')
|
|
local unit=$(echo "$size" | sed 's/[0-9.]//g' | tr '[:lower:]' '[:upper:]')
|
|
|
|
# Convert to bytes
|
|
case "$unit" in
|
|
"MB"|"M")
|
|
printf "0x%x" $((${numeric%.*} * 1024 * 1024))
|
|
;;
|
|
"KB"|"K")
|
|
printf "0x%x" $((${numeric%.*} * 1024))
|
|
;;
|
|
"GB"|"G")
|
|
printf "0x%x" $((${numeric%.*} * 1024 * 1024 * 1024))
|
|
;;
|
|
*)
|
|
# If no unit, assume it's already in hex format or bytes
|
|
if [[ "$size" =~ ^0x[0-9a-fA-F]+$ ]]; then
|
|
echo "$size"
|
|
else
|
|
printf "0x%x" "${numeric%.*}"
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Update header files based on partition configuration
|
|
update_header_files() {
|
|
# Only process qm10xv platform
|
|
if [ "$PLATFORM" != "qm10xv" ]; then
|
|
print_info "Skipping header file update for platform: $PLATFORM (only qm10xv supported)"
|
|
return 0
|
|
fi
|
|
|
|
# Skip if medium type is los_emmc
|
|
if [ "$MEDIUM_TYPE" = "los_emmc" ]; then
|
|
print_info "Skipping header file update for medium type: $MEDIUM_TYPE"
|
|
return 0
|
|
fi
|
|
|
|
# Only process los_spi-nand and los_spi-nor medium types
|
|
if [ "$MEDIUM_TYPE" != "los_spi-nand" ] && [ "$MEDIUM_TYPE" != "los_spi-nor" ]; then
|
|
print_info "Skipping header file update for medium type: $MEDIUM_TYPE (only los_spi-nand and los_spi-nor supported)"
|
|
return 0
|
|
fi
|
|
|
|
print_info "Updating qm102v.h for platform: $PLATFORM, medium type: $MEDIUM_TYPE"
|
|
|
|
# Determine qm102v.h file path
|
|
local header_file="$ROOT_DIR/base/soc/$PLATFORM/linux/board_support/uboot/uboot/board/fullhan/qm102v/$CONFIG_NAME/qm102v.h"
|
|
|
|
print_info "Target header file: $header_file"
|
|
|
|
# Check if header file exists
|
|
if [ ! -f "$header_file" ]; then
|
|
print_warning "Header file not found: $header_file"
|
|
return 0
|
|
fi
|
|
|
|
# Validate JSON configuration
|
|
if ! jq -e '.partition_table' "$CONFIG_FILE" >/dev/null 2>&1; then
|
|
print_error "Invalid JSON configuration: missing partition_table"
|
|
return 1
|
|
fi
|
|
|
|
# Create backup
|
|
local backup_file="${header_file}.backup"
|
|
cp "$header_file" "$backup_file"
|
|
print_info "Created backup: $backup_file"
|
|
|
|
# Generate mtdparts string from JSON configuration
|
|
local mtdparts_str=""
|
|
local first_partition=true
|
|
|
|
# Get total partition count to identify the last partition
|
|
local total_partitions=$(jq '.partition_table | length' "$CONFIG_FILE")
|
|
local current_partition=0
|
|
|
|
while IFS= read -r partition_json; do
|
|
current_partition=$((current_partition + 1))
|
|
local name=$(echo "$partition_json" | jq -r '.name')
|
|
local size=$(echo "$partition_json" | jq -r '.size')
|
|
local offset=$(echo "$partition_json" | jq -r '.offset')
|
|
|
|
# Convert size for mtdparts format
|
|
local mtd_size=""
|
|
if [[ "$size" =~ ([0-9]+)KB ]]; then
|
|
local kb_val="${BASH_REMATCH[1]}"
|
|
mtd_size="${kb_val}k"
|
|
elif [[ "$size" =~ ([0-9]+)MB ]]; then
|
|
local mb_val="${BASH_REMATCH[1]}"
|
|
mtd_size="${mb_val}m"
|
|
elif [[ "$size" =~ ([0-9]+\.?[0-9]*)MB ]]; then
|
|
local mb_val="${BASH_REMATCH[1]}"
|
|
# Convert decimal MB to KB
|
|
local kb_val=$(echo "$mb_val * 1024" | bc)
|
|
mtd_size="${kb_val%.*}k"
|
|
else
|
|
# Use size as-is for special cases
|
|
mtd_size="$size"
|
|
fi
|
|
|
|
# Convert offset for mtdparts format (for CONFIG_BOOTARGS)
|
|
local mtd_offset=""
|
|
if [[ "$offset" =~ 0x([0-9a-fA-F]+) ]]; then
|
|
# Use format_size_offset function to convert offset properly
|
|
mtd_offset=$(format_size_offset "$offset" "false")
|
|
else
|
|
mtd_offset="$offset"
|
|
fi
|
|
|
|
# Handle last partition (use '-' for size to indicate remaining space)
|
|
if [ $current_partition -eq $total_partitions ]; then
|
|
mtd_size="-"
|
|
fi
|
|
|
|
# Build mtdparts string for CONFIG_BOOTARGS (with size@offset format)
|
|
if [ "$first_partition" = true ]; then
|
|
mtdparts_str="${mtd_size}@${mtd_offset}(${name})"
|
|
first_partition=false
|
|
else
|
|
mtdparts_str="${mtdparts_str},${mtd_size}@${mtd_offset}(${name})"
|
|
fi
|
|
done < <(jq -r '.partition_table[] | @json' "$CONFIG_FILE")
|
|
|
|
# Generate simple mtdparts string for MTDPARTS_DEFAULT (only size and name)
|
|
local mtdparts_default_str=$mtdparts_str
|
|
|
|
print_info "Generated mtdparts for CONFIG_BOOTARGS: $mtdparts_str"
|
|
print_info "Generated mtdparts for MTDPARTS_DEFAULT: $mtdparts_default_str"
|
|
|
|
# Determine device name based on medium type
|
|
local device_name="spi0.0"
|
|
|
|
# Preserve file permissions
|
|
local file_perms=$(stat -c "%a" "$header_file")
|
|
local temp_file="${header_file}.tmp"
|
|
|
|
# Create temp file for processing
|
|
cp "$header_file" "$temp_file"
|
|
|
|
# Update MTDPARTS_DEFAULT using helper function
|
|
update_header_mtdparts_default "$header_file" "$mtdparts_default_str" "$temp_file" "$device_name"
|
|
|
|
# Update CONFIG_BOOTARGS using helper function
|
|
update_header_bootargs "$header_file" "$mtdparts_str" "$temp_file" "$device_name"
|
|
|
|
# Replace original file with modified version
|
|
mv "$temp_file" "$header_file"
|
|
|
|
# Restore file permissions
|
|
chmod "$file_perms" "$header_file"
|
|
|
|
print_info "Header file updated: $(basename "$header_file")"
|
|
print_info "Header file update completed successfully"
|
|
|
|
return 0
|
|
}
|
|
|
|
# Generate a random GUID in standard format
|
|
generate_guid() {
|
|
local hex_chars="0123456789ABCDEF"
|
|
local guid=""
|
|
|
|
# Generate 32 hex characters
|
|
for i in {1..32}; do
|
|
guid="${guid}${hex_chars:$((RANDOM % 16)):1}"
|
|
done
|
|
|
|
# Format as GUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
echo "${guid:0:8}-${guid:8:4}-${guid:12:4}-${guid:16:4}-${guid:20:12}"
|
|
}
|
|
|
|
# Convert size to KB for GPT XML
|
|
convert_size_to_kb() {
|
|
local size="$1"
|
|
|
|
# Extract numeric value and unit
|
|
local numeric=$(echo "$size" | sed 's/[^0-9.]//g')
|
|
local unit=$(echo "$size" | sed 's/[0-9.]//g' | tr '[:lower:]' '[:upper:]')
|
|
|
|
# Convert to KB
|
|
case "$unit" in
|
|
"MB"|"M")
|
|
echo $((${numeric%.*} * 1024))
|
|
;;
|
|
"KB"|"K")
|
|
echo "${numeric%.*}"
|
|
;;
|
|
"GB"|"G")
|
|
echo $((${numeric%.*} * 1024 * 1024))
|
|
;;
|
|
*)
|
|
# If no unit, assume it's already in KB
|
|
echo "${numeric%.*}"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Update programmer.ini file based on partition-config.json
|
|
update_programmer_ini() {
|
|
print_info "Checking programmer.ini update requirements..."
|
|
|
|
# Rule A: Skip if medium type is los_emmc
|
|
if [ "$MEDIUM_TYPE" = "los_emmc" ]; then
|
|
print_info "Skipping programmer.ini update: medium type is los_emmc"
|
|
return 0
|
|
fi
|
|
|
|
# Construct programmer.ini path based on platform, medium_type, and project_name
|
|
local programmer_ini_path="$ROOT_DIR/tools/partition/$PLATFORM/$MEDIUM_TYPE/$PROJECT_NAME_CONFIG/programmer.ini"
|
|
|
|
print_info "Checking for programmer.ini at: $programmer_ini_path"
|
|
|
|
# Rule B: Skip if programmer.ini doesn't exist in project directory
|
|
if [ ! -f "$programmer_ini_path" ]; then
|
|
print_info "Skipping programmer.ini update: file not found in project directory"
|
|
return 0
|
|
fi
|
|
|
|
print_info "Found programmer.ini file, proceeding with update..."
|
|
|
|
# Validate JSON configuration exists
|
|
if [ ! -f "$CONFIG_FILE" ]; then
|
|
print_error "Configuration file not found: $CONFIG_FILE"
|
|
return 1
|
|
fi
|
|
|
|
# Create backup
|
|
local backup_file="${programmer_ini_path}.backup"
|
|
cp "$programmer_ini_path" "$backup_file"
|
|
print_info "Created backup: $backup_file"
|
|
|
|
# Determine offset type based on medium type
|
|
local offset_field=""
|
|
local offset_unit=""
|
|
|
|
if [ "$MEDIUM_TYPE" = "los_spi-nand" ]; then
|
|
# For spi-nand: use BlockOffset (offset / 128KB)
|
|
offset_field="BlockOffset"
|
|
offset_unit="blocks"
|
|
local block_size_128kb=$((128 * 1024))
|
|
print_info "Using fixed block size: 128KB ($block_size_128kb bytes) for BlockOffset calculation"
|
|
elif [ "$MEDIUM_TYPE" = "los_spi-nor" ]; then
|
|
# For spi-nor: use BufferOffset (direct address)
|
|
offset_field="BufferOffset"
|
|
offset_unit="bytes"
|
|
print_info "Using BufferOffset for direct address update (no block conversion)"
|
|
else
|
|
print_warning "Unknown medium type: $MEDIUM_TYPE, defaulting to BlockOffset"
|
|
offset_field="BlockOffset"
|
|
offset_unit="blocks"
|
|
local block_size_128kb=$((128 * 1024))
|
|
fi
|
|
|
|
# Create temporary file for processing
|
|
local temp_file="${programmer_ini_path}.tmp"
|
|
cp "$programmer_ini_path" "$temp_file"
|
|
|
|
# Parse partition_table from partition-config.json and create a mapping
|
|
declare -A partition_offsets
|
|
|
|
while IFS= read -r partition_json; do
|
|
local name=$(echo "$partition_json" | jq -r '.name')
|
|
local offset=$(echo "$partition_json" | jq -r '.offset')
|
|
|
|
# Convert offset to decimal
|
|
local offset_decimal=$((offset))
|
|
|
|
# Calculate offset value based on medium type
|
|
local offset_value
|
|
if [ "$MEDIUM_TYPE" = "los_spi-nand" ]; then
|
|
# Calculate BlockOffset: offset / 128KB
|
|
offset_value=$((offset_decimal / block_size_128kb))
|
|
print_info "Partition '$name': offset=$offset, BlockOffset=$offset_value"
|
|
elif [ "$MEDIUM_TYPE" = "los_spi-nor" ]; then
|
|
# Convert offset to hex format with 'h' suffix (e.g., 0x100000 -> 100000h)
|
|
# Remove 0x prefix and add h suffix
|
|
offset_value=$(printf "%x" $offset_decimal)
|
|
offset_value="${offset_value}h"
|
|
print_info "Partition '$name': offset=$offset, BufferOffset=$offset_value"
|
|
fi
|
|
|
|
# Store in associative array
|
|
partition_offsets["$name"]=$offset_value
|
|
|
|
done < <(jq -c '.partition_table[]' "$CONFIG_FILE")
|
|
|
|
# Rule C: Update offset field in programmer.ini by matching PartitionName
|
|
local section=""
|
|
local partition_name=""
|
|
local updates_made=0
|
|
local lines_processed=0
|
|
|
|
while IFS= read -r line; do
|
|
lines_processed=$((lines_processed + 1))
|
|
|
|
# Detect section headers like [FILE0], [FILE1], etc.
|
|
if [[ "$line" =~ ^\[FILE[0-9]+\]$ ]]; then
|
|
section="$line"
|
|
partition_name=""
|
|
echo "$line" >> "$temp_file.new"
|
|
continue
|
|
fi
|
|
|
|
# Extract PartitionName
|
|
if [[ "$line" =~ ^PartitionName[[:space:]]*=[[:space:]]*(.+)$ ]]; then
|
|
partition_name=$(echo "${BASH_REMATCH[1]}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
|
echo "$line" >> "$temp_file.new"
|
|
continue
|
|
fi
|
|
|
|
# Update BlockOffset if we have a matching partition name and medium type is los_spi-nand
|
|
if [ "$MEDIUM_TYPE" = "los_spi-nand" ] && [[ "$line" =~ ^BlockOffset[[:space:]]*=[[:space:]]*(.+)$ ]] && [ -n "$partition_name" ]; then
|
|
local old_offset=$(echo "${BASH_REMATCH[1]}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
|
|
|
# Check if this partition exists in our mapping
|
|
if [ -n "${partition_offsets[$partition_name]}" ]; then
|
|
local new_offset="${partition_offsets[$partition_name]}"
|
|
|
|
if [ "$old_offset" != "$new_offset" ]; then
|
|
echo "BlockOffset =$new_offset" >> "$temp_file.new"
|
|
print_info "Updated partition '$partition_name': BlockOffset $old_offset -> $new_offset"
|
|
updates_made=$((updates_made + 1))
|
|
else
|
|
echo "$line" >> "$temp_file.new"
|
|
print_info "Partition '$partition_name': BlockOffset unchanged ($new_offset)"
|
|
fi
|
|
else
|
|
# Partition not found in JSON, keep original line
|
|
echo "$line" >> "$temp_file.new"
|
|
print_warning "Partition '$partition_name' not found in partition-config.json, keeping original BlockOffset"
|
|
fi
|
|
|
|
# Reset partition_name after processing BlockOffset
|
|
partition_name=""
|
|
continue
|
|
fi
|
|
|
|
# Update BufferOffset if we have a matching partition name and medium type is los_spi-nor
|
|
if [ "$MEDIUM_TYPE" = "los_spi-nor" ] && [[ "$line" =~ ^BufferOffset[[:space:]]*=[[:space:]]*(.+)$ ]] && [ -n "$partition_name" ]; then
|
|
local old_offset=$(echo "${BASH_REMATCH[1]}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
|
|
|
# Check if this partition exists in our mapping
|
|
if [ -n "${partition_offsets[$partition_name]}" ]; then
|
|
local new_offset="${partition_offsets[$partition_name]}"
|
|
|
|
if [ "$old_offset" != "$new_offset" ]; then
|
|
echo "BufferOffset =$new_offset" >> "$temp_file.new"
|
|
print_info "Updated partition '$partition_name': BufferOffset $old_offset -> $new_offset"
|
|
updates_made=$((updates_made + 1))
|
|
else
|
|
echo "$line" >> "$temp_file.new"
|
|
print_info "Partition '$partition_name': BufferOffset unchanged ($new_offset)"
|
|
fi
|
|
else
|
|
# Partition not found in JSON, keep original line
|
|
echo "$line" >> "$temp_file.new"
|
|
print_warning "Partition '$partition_name' not found in partition-config.json, keeping original BufferOffset"
|
|
fi
|
|
|
|
# Reset partition_name after processing BufferOffset
|
|
partition_name=""
|
|
continue
|
|
fi
|
|
|
|
# Copy all other lines as-is
|
|
echo "$line" >> "$temp_file.new"
|
|
done < "$temp_file"
|
|
|
|
# Replace original file with updated version
|
|
if [ -f "$temp_file.new" ]; then
|
|
# Preserve file permissions
|
|
chmod --reference="$programmer_ini_path" "$temp_file.new" 2>/dev/null || true
|
|
mv "$temp_file.new" "$programmer_ini_path"
|
|
rm -f "$temp_file"
|
|
|
|
if [ $updates_made -gt 0 ]; then
|
|
print_info "Successfully updated programmer.ini: $updates_made $offset_field values changed"
|
|
else
|
|
print_info "programmer.ini checked: all $offset_field values are up to date"
|
|
fi
|
|
else
|
|
print_error "Failed to create updated programmer.ini file"
|
|
rm -f "$temp_file"
|
|
return 1
|
|
fi
|
|
|
|
print_info "programmer.ini update completed"
|
|
return 0
|
|
}
|
|
|
|
# Update GPT partition table for los_emmc medium
|
|
update_gpt() {
|
|
# Check if medium type is los_emmc
|
|
if [ "$MEDIUM_TYPE" != "los_emmc" ]; then
|
|
print_info "Skipping GPT update: medium type is not los_emmc"
|
|
return 0
|
|
fi
|
|
|
|
# Check if platform is qm10xh
|
|
if [ "$PLATFORM" != "qm10xh" ]; then
|
|
print_info "Skipping GPT update: platform is not qm10xh"
|
|
return 0
|
|
fi
|
|
|
|
print_info "Updating GPT partition table for los_emmc on qm10xh"
|
|
|
|
# Construct XML file path based on medium size (keep uppercase)
|
|
local xml_dir="$ROOT_DIR/tools/partition/qm10xh/los_emmc/$PROJECT_NAME"
|
|
local xml_file="$xml_dir/qm108h_los_emmc_partition.xml"
|
|
|
|
print_info "Target XML file: $xml_file"
|
|
|
|
# Check if XML file exists
|
|
if [ ! -f "$xml_file" ]; then
|
|
print_error "GPT XML file not found: $xml_file"
|
|
return 1
|
|
fi
|
|
|
|
# Create backup
|
|
local backup_file="${xml_file}.backup"
|
|
cp "$xml_file" "$backup_file"
|
|
print_info "Created backup: $backup_file"
|
|
|
|
# Read existing partitions from XML to preserve GUIDs
|
|
declare -A existing_partitions
|
|
declare -A existing_guids
|
|
declare -A existing_sizes
|
|
|
|
# Parse XML to get existing partition labels, GUIDs, and sizes
|
|
while IFS= read -r line; do
|
|
if [[ "$line" =~ \<partition\ label=\"([^\"]+)\".*type=\"([^\"]+)\".*size_in_kb=\"([^\"]+)\" ]]; then
|
|
local label="${BASH_REMATCH[1]}"
|
|
local guid="${BASH_REMATCH[2]}"
|
|
local size_kb="${BASH_REMATCH[3]}"
|
|
existing_partitions["$label"]=1
|
|
existing_guids["$label"]="$guid"
|
|
existing_sizes["$label"]="$size_kb"
|
|
fi
|
|
done < "$xml_file"
|
|
|
|
# Extract XML header and footer
|
|
local xml_header=""
|
|
local xml_footer=""
|
|
local in_header=true
|
|
local in_footer=false
|
|
|
|
while IFS= read -r line; do
|
|
if [[ "$line" =~ \<physical_partition\> ]]; then
|
|
xml_header="${xml_header}${line}
|
|
"
|
|
in_header=false
|
|
continue
|
|
fi
|
|
|
|
if [[ "$line" =~ \</physical_partition\> ]]; then
|
|
in_footer=true
|
|
xml_footer="${xml_footer}${line}
|
|
"
|
|
continue
|
|
fi
|
|
|
|
if [ "$in_header" = true ]; then
|
|
xml_header="${xml_header}${line}
|
|
"
|
|
elif [ "$in_footer" = true ]; then
|
|
xml_footer="${xml_footer}${line}
|
|
"
|
|
fi
|
|
done < "$xml_file"
|
|
|
|
# Build new partition entries based on partition-config.json order
|
|
local new_partition_entries=""
|
|
local partitions_updated=0
|
|
local partitions_matched=0
|
|
local partitions_added=0
|
|
|
|
while IFS= read -r partition_json; do
|
|
local name=$(echo "$partition_json" | jq -r '.name')
|
|
local size=$(echo "$partition_json" | jq -r '.size')
|
|
local filename=$(echo "$partition_json" | jq -r '.filename // empty')
|
|
local fs_type=$(echo "$partition_json" | jq -r '.filesystem_type // "raw"')
|
|
local sparse_attr=$(echo "$partition_json" | jq -r '.sparse // false')
|
|
|
|
# Convert size to KB
|
|
local size_kb=$(convert_size_to_kb "$size")
|
|
|
|
# Determine sparse attribute based on filesystem type
|
|
local sparse_value="false"
|
|
if [ "$fs_type" != "raw" ] || [ "$sparse_attr" = "true" ]; then
|
|
sparse_value="true"
|
|
fi
|
|
|
|
# Determine filename
|
|
if [ -z "$filename" ]; then
|
|
if [ "$fs_type" = "raw" ] || [ "$name" = "reserve" ] || [ "$name" = "padding" ]; then
|
|
filename=""
|
|
else
|
|
filename="${name}.img"
|
|
fi
|
|
fi
|
|
|
|
# Check if partition exists in original XML
|
|
local guid=""
|
|
local status=""
|
|
|
|
if [ -n "${existing_partitions[$name]}" ]; then
|
|
# Partition exists, reuse GUID
|
|
guid="${existing_guids[$name]}"
|
|
|
|
if [ "${existing_sizes[$name]}" != "$size_kb" ]; then
|
|
# Size changed
|
|
status="updated"
|
|
print_info "Partition '$name' size changed: ${existing_sizes[$name]}KB -> ${size_kb}KB"
|
|
partitions_updated=$((partitions_updated + 1))
|
|
else
|
|
# Size matches
|
|
status="matched"
|
|
print_info "Partition '$name' size matches: ${size_kb}KB (no change)"
|
|
partitions_matched=$((partitions_matched + 1))
|
|
fi
|
|
else
|
|
# New partition, generate new GUID
|
|
guid=$(generate_guid)
|
|
status="added"
|
|
print_info "New partition '$name' added: ${size_kb}KB (sparse=$sparse_value)"
|
|
partitions_added=$((partitions_added + 1))
|
|
fi
|
|
|
|
# Build partition line
|
|
local partition_line=" <partition label=\"${name}\" filename=\"${filename}\" type=\"${guid}\" bootable=\"false\" readonly=\"false\" size_in_kb=\"${size_kb}\" sparse=\"${sparse_value}\"/>"
|
|
|
|
if [ -z "$new_partition_entries" ]; then
|
|
new_partition_entries="$partition_line"
|
|
else
|
|
new_partition_entries="${new_partition_entries}
|
|
${partition_line}"
|
|
fi
|
|
done <<< "$(jq -c '.partition_table[]' "$CONFIG_FILE")"
|
|
|
|
# Create new XML file
|
|
local temp_file="${xml_file}.tmp"
|
|
|
|
# Write XML header
|
|
printf "%s" "$xml_header" > "$temp_file"
|
|
|
|
# Write all partition entries
|
|
printf "%s\n" "$new_partition_entries" >> "$temp_file"
|
|
|
|
# Write XML footer
|
|
printf "%s" "$xml_footer" >> "$temp_file"
|
|
|
|
# Replace original file with rebuilt version
|
|
mv "$temp_file" "$xml_file"
|
|
|
|
print_info "GPT XML file rebuilt successfully"
|
|
print_info "Summary: $partitions_matched matched, $partitions_updated updated, $partitions_added added"
|
|
|
|
# Generate gpt.img using ptool.py
|
|
print_info "Generating gpt.img using ptool.py..."
|
|
|
|
local ptool_script="$ROOT_DIR/tools/partition/emmc_partition_tool/ptool.py"
|
|
|
|
if [ ! -f "$ptool_script" ]; then
|
|
print_error "ptool.py not found: $ptool_script"
|
|
return 1
|
|
fi
|
|
|
|
# Run ptool.py with Python 2
|
|
local ptool_cmd="python2 $ptool_script -x $xml_file -t $xml_dir/"
|
|
|
|
print_info "Running: $ptool_cmd"
|
|
|
|
if $ptool_cmd; then
|
|
print_info "GPT image generated successfully"
|
|
else
|
|
print_error "Failed to generate GPT image"
|
|
return 1
|
|
fi
|
|
|
|
# Rename and cleanup generated files
|
|
print_info "Renaming generated files..."
|
|
|
|
# Rename gpt_main0.bin to gpt_qm108h_los_emmc.bin
|
|
if [ -f "${xml_dir}/gpt_main0.bin" ]; then
|
|
mv "${xml_dir}/gpt_main0.bin" "${xml_dir}/gpt_qm108h_los_emmc.bin"
|
|
print_info "Renamed: gpt_main0.bin -> gpt_qm108h_los_emmc.bin"
|
|
else
|
|
print_warning "gpt_main0.bin not found, skipping rename"
|
|
fi
|
|
|
|
# Rename rawprogram0.xml to qm108h_los_emmc_partition_o.xml
|
|
if [ -f "${xml_dir}/rawprogram0.xml" ]; then
|
|
mv "${xml_dir}/rawprogram0.xml" "${xml_dir}/qm108h_los_emmc_partition_o.xml"
|
|
print_info "Renamed: rawprogram0.xml -> qm108h_los_emmc_partition_o.xml"
|
|
else
|
|
print_warning "rawprogram0.xml not found, skipping rename"
|
|
fi
|
|
|
|
# Change permissions for all files generated by ptool.py (set to 644)
|
|
print_info "Setting file permissions for generated files..."
|
|
|
|
# Find all files in xml_dir (excluding backup files)
|
|
for file in "$xml_dir"/*; do
|
|
if [ -f "$file" ]; then
|
|
local filename=$(basename "$file")
|
|
# Skip backup files
|
|
if [[ ! "$filename" =~ \.backup$ ]]; then
|
|
chmod 775 "$file" 2>/dev/null || true
|
|
fi
|
|
fi
|
|
done
|
|
|
|
print_info "File permissions set to 775 for all generated files"
|
|
|
|
print_info "GPT update completed successfully"
|
|
return 0
|
|
}
|
|
|
|
# Main execution
|
|
main() {
|
|
print_info "=== XOS Partition Configuration Update ==="
|
|
|
|
# Check dependencies
|
|
check_dependencies
|
|
|
|
# Validate configuration
|
|
validate_config
|
|
|
|
# Display configuration summary
|
|
print_info "Configuration Summary:"
|
|
print_info " Project: $PROJECT_NAME_CONFIG"
|
|
print_info " Config: $CONFIG_NAME"
|
|
print_info " Platform: $PLATFORM"
|
|
print_info " Medium: $MEDIUM_TYPE ($MEDIUM_SIZE)"
|
|
print_info " OS: $OS_TYPE"
|
|
|
|
# Generate files
|
|
generate_partition_info
|
|
update_defconfig
|
|
update_header_files
|
|
update_programmer_ini
|
|
update_gpt
|
|
|
|
print_info "=== Partition configuration update completed successfully ==="
|
|
print_info "Modified files:"
|
|
print_info " - product/$PROJECT_NAME/partition-info.txt"
|
|
|
|
case "$PLATFORM" in
|
|
"qm10xd")
|
|
print_info " - base/soc/qm10xd/$OS_TYPE/bsp/uboot/uboot/configs/quaming_qm10xd_${CONFIG_NAME}_defconfig"
|
|
if [ "$MEDIUM_TYPE" != "los_emmc" ] && [ -f "$ROOT_DIR/tools/partition/$PLATFORM/$MEDIUM_TYPE/$PROJECT_NAME_CONFIG/programmer.ini" ]; then
|
|
print_info " - tools/partition/$PLATFORM/$MEDIUM_TYPE/$PROJECT_NAME_CONFIG/programmer.ini"
|
|
fi
|
|
;;
|
|
"qm10xv")
|
|
print_info " - base/soc/qm10xv/$OS_TYPE/board_support/uboot/uboot/board/fullhan/qm102v/$CONFIG_NAME/qm102v.h"
|
|
if [ "$MEDIUM_TYPE" != "los_emmc" ] && [ -f "$ROOT_DIR/tools/partition/$PLATFORM/$MEDIUM_TYPE/$PROJECT_NAME_CONFIG/programmer.ini" ]; then
|
|
print_info " - tools/partition/$PLATFORM/$MEDIUM_TYPE/$PROJECT_NAME_CONFIG/programmer.ini"
|
|
fi
|
|
;;
|
|
"qm10xh")
|
|
if [ "$MEDIUM_TYPE" = "los_emmc" ]; then
|
|
print_info " - tools/partition/qm10xh/los_emmc/$PROJECT_NAME/qm108h_los_emmc_partition.xml"
|
|
print_info " - tools/partition/qm10xh/los_emmc/$PROJECT_NAME/gpt_qm108h_los_emmc.bin"
|
|
print_info " - tools/partition/qm10xh/los_emmc/$PROJECT_NAME/qm108h_los_emmc_partition_o.xml"
|
|
else
|
|
print_info " - base/soc/qm10xh/$OS_TYPE/bsp/uboot/uboot/configs/quaming_qm108h_${CONFIG_NAME}_defconfig"
|
|
if [ -f "$ROOT_DIR/tools/partition/$PLATFORM/$MEDIUM_TYPE/$PROJECT_NAME_CONFIG/programmer.ini" ]; then
|
|
print_info " - tools/partition/$PLATFORM/$MEDIUM_TYPE/$PROJECT_NAME_CONFIG/programmer.ini"
|
|
fi
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
print_info ""
|
|
print_info "Next steps:"
|
|
print_info " 1. Review the generated files"
|
|
print_info " 2. Run your build command"
|
|
print_info " 3. Test the new partition configuration"
|
|
}
|
|
|
|
# Execute main function
|
|
main "$@"
|