1#!/bin/bash 2 3# Make sure that we are sourced and called inside of RK build scripts. 4if [ "$BASH_SOURCE" = "$0" -o -z "$RK_SESSION" ];then 5 echo "$(realpath $0) is not supposed to be executed directly" 6 exit 1 7fi 8 9# Parsed partition table file 10PART_TABLE="$RK_LOG_DIR/part-table" 11 12# Hidden header partition (part-table and idblock) 13HDR_PART="<hidden>" 14 15rk_partition_size_sector_to_readable() 16{ 17 # Consider 0 as unlimited 18 case "${1:-grow}" in 19 - | 0 | grow) 20 echo grow 21 return 0 ;; 22 esac 23 24 SIZE=$(( $1 * 512 )) 25 if [ "$SIZE" -lt 1024 ]; then 26 echo $SIZE 27 elif [ "$SIZE" -ge $(( 1024 * 1024 * 1024 )) ]; then 28 echo "$(echo "scale=1; $SIZE / 1024 / 1024 / 1024" | bc | \ 29 sed 's/\.0$//')G" 30 elif [ "$SIZE" -ge $(( 1024 * 1024 )) ]; then 31 echo "$(echo "scale=1; $SIZE / 1024 / 1024" | bc | \ 32 sed 's/\.0$//')M" 33 else 34 echo "$(echo "scale=1; $SIZE / 1024" | bc | \ 35 sed 's/\.0$//')K" 36 fi 37} 38 39rk_partition_size_readable_to_sector() 40{ 41 SIZE=${1%B} 42 43 case "${SIZE:-grow}" in 44 # Consider 0 as unlimited 45 - | 0 | grow) 46 echo '-' 47 return 0 48 ;; 49 0x*) 50 echo $SIZE 51 return 0 52 ;; 53 esac 54 55 { 56 case "$SIZE" in 57 *K) echo "${SIZE%K} * 2" | bc ;; 58 *M) echo "${SIZE%M} * 2 * 1024" | bc ;; 59 *G) echo "${SIZE%G} * 2 * 1024 * 1024" | bc ;; 60 *) echo "$SIZE / 512" | bc ;; 61 esac 62 } | cut -d'.' -f1 | awk '{printf "0x%08x",$1}' 63} 64 65# Parse parameter to "<name> <size>" pairs 66rk_partition_parse() 67{ 68 PARAMETER="${1:-$CHIP_DIR/$RK_PARAMETER}" 69 70 if [ ! -r "$PARAMETER" ]; then 71 echo -e "\e[36m$PARAMETER not exists!\e[0m" >&2 72 exit 1 73 fi 74 75 PARTS="$(grep "^CMDLINE:" "$PARAMETER" | grep -o "0x.*")" 76 77 # NOTE: Assuming partitions are contiguous 78 echo "$HDR_PART $(echo $PARTS | awk -F '[@():]' '{print $2}')" 79 echo "${PARTS//,/ }" | xargs -n 1 | \ 80 awk -F '[@():]' '{print $3,$1}' 81} 82 83# Parse parameter to "<name>" arrays 84rk_partition_parse_names() 85{ 86 rk_partition_parse "$1" | grep -v "^$HDR_PART " | cut -d' ' -f1 | xargs 87} 88 89# Cache parsed partition table 90rk_partition_init() 91{ 92 rk_partition_parse > "$PART_TABLE" 93} 94 95rk_partition_size() 96{ 97 grep "^$1 " "$PART_TABLE" | cut -d' ' -f2 | tr -d '\-' || true 98} 99 100rk_partition_num() 101{ 102 echo $(( $(cat "$PART_TABLE" | wc -l) - 1 )) 103} 104 105# Print partition table info 106rk_partition_print() 107{ 108 echo 109 echo "==========================================" 110 echo " Partition table" 111 echo "==========================================" 112 { 113 OFFSET=0 114 while read NAME SIZE; do 115 OFFSET=$(echo $OFFSET | awk '{printf "0x%08x",$1}') 116 SIZE_STR=$(rk_partition_size_sector_to_readable $SIZE) 117 118 if [ "$NAME" != "$HDR_PART" ]; then 119 NAME=$(echo $NAME | awk '{printf "%12s",$1}') 120 echo -e "$NAME at $OFFSET size=$SIZE($SIZE_STR)" 121 fi 122 123 # NOTE: Assuming partitions are contiguous 124 OFFSET=$(( $OFFSET + ${SIZE/-/0} )) 125 done < "$PART_TABLE" 126 } | sed "=" | sed "N;s/\n/: /" 127 128 echo 129 echo "Legacy cmdline:" 130 rk_partition_to_cmdline 131 echo 132} 133 134# Convert partition table to Rockchip legacy cmdline format 135rk_partition_to_cmdline() 136{ 137 OFFSET=0 138 while read NAME SIZE; do 139 case "$SIZE" in 140 -) 141 # Latest grow part 142 echo "$NAME $OFFSET" | \ 143 awk '{printf "-@0x%08x(%s:grow)",$2,$1}' 144 break ;; 145 *) SIZE=$(rk_partition_size_readable_to_sector $SIZE) ;; 146 esac 147 148 # Visible parts 149 if [ "$NAME" != "$HDR_PART" ]; then 150 echo "$NAME $OFFSET $(( $SIZE ))" | \ 151 awk '{printf "0x%08x@0x%08x(%s)",$3,$2,$1}' 152 fi 153 154 # NOTE: Assuming partitions are contiguous 155 OFFSET=$(( $OFFSET + $SIZE )) 156 done < "$PART_TABLE" | sed 's/)\([^$]\)/),\1/g' 157} 158 159# Save partition table to parameter 160rk_partition_save() 161{ 162 PARAMETER="${1:-$CHIP_DIR/$RK_PARAMETER}" 163 [ -r "$PARAMETER" ] || return 1 164 165 PARTS=$(rk_partition_to_cmdline) 166 [ "$PARTS" ] || return 1 167 168 sed -i "/^CMDLINE:/s/0x.*/$PARTS/" "$PARAMETER" 169 170 # Reflush 171 rk_partition_init 172} 173 174# Edit raw partition table 175rk_partition_edit() 176{ 177 sed -i '1i # name size' "$PART_TABLE" 178 eval ${EDITOR:-vi} "$PART_TABLE" 179 sed -i '/#/d' "$PART_TABLE" 180 rk_partition_save 181} 182 183rk_partition_parse_name() 184{ 185 unset PART_NAME 186 187 [ "$#" -eq 1 ] || return 1 188 189 # Part name 190 if ! echo $1 | grep -qE "^[0-9]*$"; then 191 if ! grep -q "^$1 " "$PART_TABLE"; then 192 echo -e "\e[35mNo such part ($1)!\e[0m" 193 return 1 194 fi 195 196 PART_NAME=$1 197 return 0 198 fi 199 200 # Part idx 201 IDX=$1 202 if [ "$IDX" -lt 1 ]; then 203 echo -e "\e[35mIndex should not be less than 1!\e[0m" 204 return 1 205 fi 206 207 NUM=$(rk_partition_num) 208 if [ "$IDX" -gt "$NUM" ]; then 209 echo -e "\e[35mIndex should not be greater than $NUM!\e[0m" 210 return 1 211 fi 212 213 PART_NAME=$(sed -n "$(($IDX + 1))s/\(^[^ ]*\) .*/\1/p" "$PART_TABLE") 214} 215 216rk_partition_del() 217{ 218 [ "$#" -gt 0 ] || return 1 219 220 rk_partition_parse_name $1 || return 1 221 sed -i "/^$PART_NAME /d" "$PART_TABLE" 222 223 rk_partition_save 224} 225 226rk_partition_rename() 227{ 228 [ "$#" -gt 1 ] || return 1 229 230 echo $2 | grep -qE "^[a-zA-Z]" || return 1 231 if rk_partition_parse_name $2 >/dev/null; then 232 echo -e "\e[35mPart already exists ($2)!\e[0m" 233 return 1 234 fi 235 236 rk_partition_parse_name $1 || return 1 237 sed -i "s/^$PART_NAME /$2 /" "$PART_TABLE" 238 239 rk_partition_save 240} 241 242rk_partition_move() 243{ 244 [ "$#" -gt 1 ] || return 1 245 246 echo $2 | grep -qE "^[0-9]*$" || return 1 247 rk_partition_parse_name $2 || return 1 248 249 rk_partition_parse_name $1 || return 1 250 PART=$(sed -n "/^$PART_NAME /p" "$PART_TABLE") 251 252 NUM=$(rk_partition_num) 253 if [ "$2" -eq "$NUM" ] && grep -q "\-$" "$PART_TABLE"; then 254 echo -e "\e[35mCannot move after unlimited part!\e[0m" 255 return 1 256 fi 257 258 if echo "$PART" | grep -q "\-$"; then 259 echo -e "\e[35mCannot move unlimited part ($1)!\e[0m" 260 return 1 261 fi 262 263 sed -i "/^$PART$/d" "$PART_TABLE" 264 sed -i "$2 a$PART" "$PART_TABLE" 265 266 rk_partition_save 267} 268 269rk_partition_resize() 270{ 271 [ "$#" -gt 1 ] || return 1 272 273 case "$2" in 274 0x*) SIZE=$2 ;; 275 *) SIZE="$(rk_partition_size_readable_to_sector $2)" ;; 276 esac 277 278 rk_partition_parse_name $1 || return 1 279 sed -i "s/^$PART_NAME .*/$PART_NAME $SIZE/" "$PART_TABLE" 280 281 rk_partition_save 282} 283 284rk_partition_insert() 285{ 286 [ "$#" -gt 1 ] || return 1 287 288 echo $1 | grep -qE "^[0-9]*$" || return 1 289 290 IDX=$1 291 if [ "$IDX" -lt 1 ]; then 292 echo -e "\e[35mIndex should not be less than 1!\e[0m" 293 return 1 294 fi 295 296 NUM=$(rk_partition_num) 297 if [ "$IDX" -gt "$(($NUM + 1))" ]; then 298 echo -e "\e[35mIndex should not be greater than $(($NUM + 1))!\e[0m" 299 return 1 300 fi 301 302 echo $2 | grep -qE "^[a-zA-Z]" || return 1 303 if rk_partition_parse_name $2 >/dev/null; then 304 echo -e "\e[35mPart already exists ($2)!\e[0m" 305 return 1 306 fi 307 308 case "${3:-grow}" in 309 0x*) SIZE=$3 ;; 310 *) SIZE="$(rk_partition_size_readable_to_sector $3)" ;; 311 esac 312 313 if [ "$SIZE" = "-" ] && [ "$IDX" -lt "$(( $NUM + 1 ))" ]; then 314 echo -e "\e[35mOnly latest part can be unlimited!\e[0m" 315 return 1 316 fi 317 318 if [ "$IDX" -eq "$(( $NUM + 1 ))" ] && grep -q "\-$" "$PART_TABLE"; then 319 echo -e "\e[35mCannot insert after unlimited part!\e[0m" 320 return 1 321 fi 322 323 sed -i "$IDX a$2 $SIZE" "$PART_TABLE" 324 325 rk_partition_save 326} 327 328# Usage: <offset> <name> <size> <name> <size>... 329rk_partition_create() 330{ 331 [ "$#" -gt 1 ] || return 1 332 333 { 334 echo "$HDR_PART $(echo $(( $1 )) | awk '{printf "0x%08x",$1}')" 335 shift 336 337 while [ "$1" ]; do 338 NAME=$1 339 shift 340 341 SIZE="$(rk_partition_size_readable_to_sector $1)" 342 [ -z "$1" ] || shift 343 344 if [ "$1" -a "$SIZE" = "-" ]; then 345 echo -e "\e[35mOnly latest part can be unlimited!\e[0m" 346 break 347 fi 348 349 echo "$NAME $SIZE" 350 done 351 } > "$PART_TABLE" 352 353 rk_partition_save 354} 355 356# -------- extra partition helpers -------- # 357 358rk_extra_part_num() 359{ 360 echo ${RK_EXTRA_PARTITION_NUM:-0} 361} 362 363rk_extra_part_cfg() 364{ 365 [ "$RK_EXTRA_PARTITION_STR" ] || return 0 366 367 RK_EXTRA_PARTITION_ARRAY=( $(echo ${RK_EXTRA_PARTITION_STR//@/ } | \ 368 xargs -n 1 | sort) ) 369 PART_IDX=$(( ${1:-1} - 1 )) 370 echo "${RK_EXTRA_PARTITION_ARRAY[$PART_IDX]}" 371} 372 373rk_extra_part_arg() 374{ 375 PART="$(rk_extra_part_cfg ${1:-1})" 376 ARG="$(echo "$PART" | cut -d':' -f${2:-1})" 377 echo "${ARG:-$3}" 378} 379 380rk_extra_part_dev() 381{ 382 rk_extra_part_arg ${1:-1} 1 383} 384 385rk_extra_part_name() 386{ 387 rk_extra_part_arg ${1:-1} 2 388} 389 390rk_extra_part_mountpoint() 391{ 392 rk_extra_part_arg ${1:-1} 3 "/$(rk_extra_part_name $1)" 393} 394 395rk_extra_part_fstype() 396{ 397 rk_extra_part_arg ${1:-1} 4 ext4 398} 399 400rk_extra_part_options() 401{ 402 rk_extra_part_arg ${1:-1} 5 defaults 403} 404 405rk_extra_part_src() 406{ 407 PART_NAME="$(rk_extra_part_name $1)" 408 for src in $(rk_extra_part_arg ${1:-1} 6 | tr ',' ' '); do 409 # Src is either relative path to $RK_IMAGE_DIR/<name>/, or \ 410 # absolute path. 411 if echo "$src" | grep -vq "^/"; then 412 echo "$RK_IMAGE_DIR/$PART_NAME/${PART_NAME}_${src}" 413 else 414 echo "$src" 415 fi 416 done 417} 418 419rk_extra_part_size() 420{ 421 rk_extra_part_arg ${1:-1} 7 auto 422} 423 424rk_extra_part_fixed() 425{ 426 rk_extra_part_arg ${1:-1} 8 | grep -wq fixed 427} 428 429rk_extra_part_builtin() 430{ 431 rk_extra_part_arg ${1:-1} 8 | grep -wq builtin 432} 433 434# Symlink to the mountpoint in rootfs dir 435rk_extra_part_mount_dir() 436{ 437 echo "$RK_OUTDIR/$(rk_extra_part_name $1)-mount" 438} 439 440rk_extra_part_outdir() 441{ 442 echo "$RK_OUTDIR/$(rk_extra_part_name $1)" 443} 444 445rk_extra_part_fakeroot_script() 446{ 447 echo "$(rk_extra_part_outdir $1).fs" 448} 449 450rk_extra_part_img() 451{ 452 echo "$RK_FIRMWARE_DIR/$(rk_extra_part_name $1).img" 453} 454 455# Prepare extra part's files and fakeroot script 456rk_extra_part_prepare() 457{ 458 PART_NAME="$(rk_extra_part_name $1)" 459 OUTDIR="$(rk_extra_part_outdir $1)" 460 MOUNT_DIR="$(rk_extra_part_mount_dir $1)" 461 FAKEROOT_SCRIPT="$(rk_extra_part_fakeroot_script $1)" 462 SRCS="$(rk_extra_part_src $1)" 463 464 echo "Preparing partiton $PART_NAME" 465 466 rm -rf "$OUTDIR" "$FAKEROOT_SCRIPT" 467 468 if [ ! "$SRCS" ]; then 469 echo "Ignoring $PART_NAME for no sources" 470 return 0 471 fi 472 473 mkdir -p "$OUTDIR" 474 475 if rk_extra_part_fixed $idx; then 476 if ! rk_extra_part_builtin $idx; then 477 # Skip boot-time resizing by adding a tag file 478 touch "$OUTDIR/.fixed" 479 fi 480 fi 481 482 echo "#!/bin/sh -e" > "$FAKEROOT_SCRIPT" 483 chmod a+x "$FAKEROOT_SCRIPT" 484 485 for src in $MOUNT_DIR $SRCS; do 486 [ -d "$src" ] || continue 487 [ "$(ls "$src/")" ] || continue 488 489 echo "Merging $src into $OUTDIR" 490 rsync -a "$src/" "$OUTDIR" 491 for f in $(ls "$OUTDIR" | grep "\.fs$" || true); do 492 echo "Merging $src/$f into $FAKEROOT_SCRIPT" 493 cat "$OUTDIR/$f" >> "$FAKEROOT_SCRIPT" 494 rm -f "$OUTDIR/$f" 495 done 496 done 497} 498