1#!/bin/bash 2# 3# Copyright (C) 2018 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18set -e 19set -u 20 21SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P) 22 23usage() { 24 echo -n "usage: $0 [-h] [-s bullseye|bullseye-cuttlefish|bullseye-rockpi|bullseye-server] " 25 echo -n "[-a i386|amd64|armhf|arm64] -k /path/to/kernel " 26 echo -n "-i /path/to/initramfs.gz [-d /path/to/dtb:subdir] " 27 echo "[-m http://mirror/debian] [-n rootfs|disk] [-r initrd] [-e] [-g]" 28 exit 1 29} 30 31mirror=http://ftp.debian.org/debian 32embed_kernel_initrd_dtb=0 33install_grub=0 34suite=bullseye 35arch=amd64 36 37dtb_subdir= 38initramfs= 39kernel= 40ramdisk= 41disk= 42dtb= 43 44while getopts ":hs:a:m:n:r:k:O:i:d:eg" opt; do 45 case "${opt}" in 46 h) 47 usage 48 ;; 49 s) 50 if [[ "${OPTARG%-*}" != "bullseye" ]]; then 51 echo "Invalid suite: ${OPTARG}" >&2 52 usage 53 fi 54 suite="${OPTARG}" 55 ;; 56 a) 57 arch="${OPTARG}" 58 ;; 59 m) 60 mirror="${OPTARG}" 61 ;; 62 n) 63 disk="${OPTARG}" 64 ;; 65 r) 66 ramdisk="${OPTARG}" 67 ;; 68 k) 69 kernel="${OPTARG}" 70 ;; 71 O) 72 extradeb="${OPTARG}" 73 ;; 74 i) 75 initramfs="${OPTARG}" 76 ;; 77 d) 78 dtb="${OPTARG%:*}" 79 if [ "${OPTARG#*:}" != "${dtb}" ]; then 80 dtb_subdir="${OPTARG#*:}/" 81 fi 82 ;; 83 e) 84 embed_kernel_initrd_dtb=1 85 ;; 86 g) 87 install_grub=1 88 ;; 89 \?) 90 echo "Invalid option: ${OPTARG}" >&2 91 usage 92 ;; 93 :) 94 echo "Invalid option: ${OPTARG} requires an argument" >&2 95 usage 96 ;; 97 esac 98done 99 100# Disable Debian's "persistent" network device renaming 101cmdline="net.ifnames=0 rw 8250.nr_uarts=2 PATH=/usr/sbin:/bin:/usr/bin" 102cmdline="${cmdline} embed_kernel_initrd_dtb=${embed_kernel_initrd_dtb}" 103cmdline="${cmdline} install_grub=${install_grub}" 104 105case "${arch}" in 106 i386) 107 cmdline="${cmdline} console=ttyS0 exitcode=/dev/ttyS1" 108 machine="pc-i440fx-2.8,accel=kvm" 109 qemu="qemu-system-i386" 110 partguid="8303" 111 cpu="max" 112 ;; 113 amd64) 114 cmdline="${cmdline} console=ttyS0 exitcode=/dev/ttyS1" 115 machine="pc-i440fx-2.8,accel=kvm" 116 qemu="qemu-system-x86_64" 117 partguid="8304" 118 cpu="max" 119 ;; 120 armhf) 121 cmdline="${cmdline} console=ttyAMA0 exitcode=/dev/ttyS0" 122 machine="virt,gic-version=2" 123 qemu="qemu-system-arm" 124 partguid="8307" 125 cpu="cortex-a15" 126 ;; 127 arm64) 128 cmdline="${cmdline} console=ttyAMA0 exitcode=/dev/ttyS0" 129 machine="virt,gic-version=2" 130 qemu="qemu-system-aarch64" 131 partguid="8305" 132 cpu="cortex-a53" # "max" is too slow 133 ;; 134 *) 135 echo "Invalid arch: ${OPTARG}" >&2 136 usage 137 ;; 138esac 139 140if [[ -z "${disk}" ]]; then 141 if [[ "${install_grub}" = "1" ]]; then 142 base_image_name=disk 143 else 144 base_image_name=rootfs 145 fi 146 disk="${base_image_name}.${arch}.${suite}.$(date +%Y%m%d)" 147fi 148disk=$(realpath "${disk}") 149 150if [[ -z "${ramdisk}" ]]; then 151 ramdisk="initrd.${arch}.${suite}.$(date +%Y%m%d)" 152fi 153ramdisk=$(realpath "${ramdisk}") 154 155if [[ -z "${kernel}" ]]; then 156 echo "$0: Path to kernel image must be specified (with '-k')" 157 usage 158elif [[ ! -e "${kernel}" ]]; then 159 echo "$0: Kernel image not found at '${kernel}'" 160 exit 2 161fi 162 163if [[ -z "${initramfs}" ]]; then 164 echo "Path to initial ramdisk image must be specified (with '-i')" 165 usage 166elif [[ ! -e "${initramfs}" ]]; then 167 echo "Initial ramdisk image not found at '${initramfs}'" 168 exit 3 169fi 170 171# Sometimes it isn't obvious when the script fails 172failure() { 173 echo "Filesystem generation process failed." >&2 174 rm -f "${disk}" "${ramdisk}" 175} 176trap failure ERR 177 178# Import the package list for this release 179packages=$(cpp "${SCRIPT_DIR}/rootfs/${suite}.list" | grep -v "^#" | xargs | tr -s ' ' ',') 180 181# For the debootstrap intermediates 182tmpdir=$(mktemp -d) 183tmpdir_remove() { 184 echo "Removing temporary files.." >&2 185 sudo rm -rf "${tmpdir}" 186} 187trap tmpdir_remove EXIT 188 189workdir="${tmpdir}/_" 190mkdir "${workdir}" 191chmod 0755 "${workdir}" 192sudo chown root:root "${workdir}" 193 194# Run the debootstrap first 195cd "${workdir}" 196 197retries=5 198while ! sudo debootstrap --arch="${arch}" --variant=minbase --include="${packages}" \ 199 --foreign "${suite%-*}" . "${mirror}"; do 200 retries=$((${retries} - 1)) 201 if [ ${retries} -le 0 ]; then 202 failure 203 exit 1 204 fi 205 echo "debootstrap failed - trying again - ${retries} retries left" 206done 207 208# Copy some bootstrapping scripts into the rootfs 209sudo cp -a "${SCRIPT_DIR}"/rootfs/*.sh root/ 210sudo cp -a "${SCRIPT_DIR}"/rootfs/net_test.sh sbin/net_test.sh 211sudo chown root:root sbin/net_test.sh 212 213# Extract the ramdisk to bootstrap with to / 214lz4 -lcd "${initramfs}" | sudo cpio -idum lib/modules/* 215 216# Create /host, for the pivot_root and 9p mount use cases 217sudo mkdir host 218 219# debootstrap workaround: Run debootstrap in docker sometimes causes the 220# /proc being a symlink in first stage. We need to fix the symlink to an empty 221# directory. 222if [ -L "${workdir}/proc" ]; then 223 echo "/proc in debootstrap 1st stage is a symlink. Fixed!" 224 sudo rm -f "${workdir}/proc" 225 sudo mkdir "${workdir}/proc" 226fi 227 228# Leave the workdir, to build the filesystem 229cd - 230 231# For the initial ramdisk, and later for the final rootfs 232mount=$(mktemp -d) 233mount_remove() { 234 rmdir "${mount}" 235 tmpdir_remove 236} 237trap mount_remove EXIT 238 239# The initial ramdisk filesystem must be <=512M, or QEMU's -initrd 240# option won't touch it 241initrd=$(mktemp) 242initrd_remove() { 243 rm -f "${initrd}" 244 mount_remove 245} 246trap initrd_remove EXIT 247truncate -s 512M "${initrd}" 248/sbin/mke2fs -F -t ext4 -L ROOT "${initrd}" 249 250# Mount the new filesystem locally 251sudo mount -o loop -t ext4 "${initrd}" "${mount}" 252image_unmount() { 253 sudo umount "${mount}" 254 initrd_remove 255} 256trap image_unmount EXIT 257 258# Copy the patched debootstrap results into the new filesystem 259sudo cp -a "${workdir}"/* "${mount}" 260sudo rm -rf "${workdir}" 261 262# Unmount the initial ramdisk 263sudo umount "${mount}" 264trap initrd_remove EXIT 265 266if [[ "${install_grub}" = 1 ]]; then 267 part_num=0 268 # $1 partition size 269 # $2 gpt partition type 270 # $3 partition name 271 # $4 bypass alignment checks (use on <1MB partitions only) 272 # $5 partition attribute bit to set 273 sgdisk() { 274 part_num=$((part_num+1)) 275 [[ -n "${4:-}" ]] && prefix="-a1" || prefix= 276 [[ -n "${5:-}" ]] && suffix="-A:${part_num}:set:$5" || suffix= 277 /sbin/sgdisk ${prefix} \ 278 "-n:${part_num}:$1" "-t:${part_num}:$2" "-c:${part_num}:$3" \ 279 ${suffix} "${disk}" >/dev/null 2>&1 280 } 281 # If there's a bootloader, we need to make space for the GPT header, GPT 282 # footer and EFI system partition (legacy boot is not supported) 283 # Keep this simple - modern gdisk reserves 1MB for the GPT header and 284 # assumes all partitions are 1MB aligned 285 truncate -s "$((1 + 128 + 10 * 1024 + 1))M" "${disk}" 286 /sbin/sgdisk --zap-all "${disk}" >/dev/null 2>&1 287 # On RockPi devices, steal a bit of space at the start of the disk for 288 # some special bootloader partitions. Some of these have to start/end 289 # at specific offsets as well 290 if [[ "${suite#*-}" = "rockpi" ]]; then 291 # See https://opensource.rock-chips.com/wiki_Boot_option 292 # Keep in sync with rootfs/*-rockpi.sh 293 sgdisk "64:8127" "8301" "idbloader" "true" 294 sgdisk "8128:+64" "8301" "uboot_env" "true" 295 sgdisk "8M:+4M" "8301" "uboot" 296 sgdisk "12M:+4M" "8301" "trust" 297 sgdisk "16M:+1M" "8301" "misc" 298 sgdisk "17M:+128M" "ef00" "esp" "" "0" 299 sgdisk "145M:0" "8305" "rootfs" "" "2" 300 system_partition="6" 301 rootfs_partition="7" 302 else 303 sgdisk "0:+128M" "ef00" "esp" "" "0" 304 sgdisk "0:0" "${partguid}" "rootfs" "" "2" 305 system_partition="1" 306 rootfs_partition="2" 307 fi 308 309 # Create an empty EFI system partition; it will be initialized later 310 system_partition_start=$(partx -g -o START -s -n "${system_partition}" "${disk}" | xargs) 311 system_partition_end=$(partx -g -o END -s -n "${system_partition}" "${disk}" | xargs) 312 system_partition_num_sectors=$((${system_partition_end} - ${system_partition_start} + 1)) 313 system_partition_num_vfat_blocks=$((${system_partition_num_sectors} / 2)) 314 /sbin/mkfs.vfat -n SYSTEM -F 16 --offset=${system_partition_start} "${disk}" ${system_partition_num_vfat_blocks} >/dev/null 315 # Copy the rootfs to just after the EFI system partition 316 rootfs_partition_start=$(partx -g -o START -s -n "${rootfs_partition}" "${disk}" | xargs) 317 rootfs_partition_end=$(partx -g -o END -s -n "${rootfs_partition}" "${disk}" | xargs) 318 rootfs_partition_num_sectors=$((${rootfs_partition_end} - ${rootfs_partition_start} + 1)) 319 rootfs_partition_offset=$((${rootfs_partition_start} * 512)) 320 rootfs_partition_size=$((${rootfs_partition_num_sectors} * 512)) 321 dd if="${initrd}" of="${disk}" bs=512 seek="${rootfs_partition_start}" conv=fsync,notrunc 2>/dev/null 322 /sbin/e2fsck -p -f "${disk}"?offset=${rootfs_partition_offset} || true 323 disksize=$(stat -c %s "${disk}") 324 /sbin/resize2fs "${disk}"?offset=${rootfs_partition_offset} ${rootfs_partition_num_sectors}s 325 truncate -s "${disksize}" "${disk}" 326 /sbin/sgdisk -e "${disk}" 327 /sbin/e2fsck -p -f "${disk}"?offset=${rootfs_partition_offset} || true 328 /sbin/e2fsck -fy "${disk}"?offset=${rootfs_partition_offset} || true 329else 330 # If there's no bootloader, the initrd is the disk image 331 cp -a "${initrd}" "${disk}" 332 truncate -s 10G "${disk}" 333 /sbin/e2fsck -p -f "${disk}" || true 334 /sbin/resize2fs "${disk}" 335 system_partition= 336 rootfs_partition="raw" 337fi 338 339# Create another fake block device for initrd.img writeout 340raw_initrd=$(mktemp) 341raw_initrd_remove() { 342 rm -f "${raw_initrd}" 343 initrd_remove 344} 345trap raw_initrd_remove EXIT 346truncate -s 64M "${raw_initrd}" 347 348# Get number of cores for qemu. Restrict the maximum value to 8. 349qemucpucores=$(nproc) 350if [[ ${qemucpucores} -gt 8 ]]; then 351 qemucpucores=8 352fi 353 354# Complete the bootstrap process using QEMU and the specified kernel 355${qemu} -machine "${machine}" -cpu "${cpu}" -m 2048 >&2 \ 356 -kernel "${kernel}" -initrd "${initrd}" -no-user-config -nodefaults \ 357 -no-reboot -display none -nographic -serial stdio -parallel none \ 358 -smp "${qemucpucores}",sockets="${qemucpucores}",cores=1,threads=1 \ 359 -object rng-random,id=objrng0,filename=/dev/urandom \ 360 -device virtio-rng-pci-non-transitional,rng=objrng0,id=rng0,max-bytes=1024,period=2000 \ 361 -drive file="${disk}",format=raw,if=none,aio=threads,id=drive-virtio-disk0 \ 362 -device virtio-blk-pci-non-transitional,scsi=off,drive=drive-virtio-disk0 \ 363 -drive file="${raw_initrd}",format=raw,if=none,aio=threads,id=drive-virtio-disk1 \ 364 -device virtio-blk-pci-non-transitional,scsi=off,drive=drive-virtio-disk1 \ 365 -chardev file,id=exitcode,path=exitcode \ 366 -device pci-serial,chardev=exitcode \ 367 -append "root=/dev/ram0 ramdisk_size=524288 init=/root/stage1.sh ${cmdline}" 368[[ -s exitcode ]] && exitcode=$(cat exitcode | tr -d '\r') || exitcode=2 369rm -f exitcode 370if [ "${exitcode}" != "0" ]; then 371 echo "Second stage debootstrap failed (err=${exitcode})" 372 exit "${exitcode}" 373fi 374 375# Fix up any issues from the unclean shutdown 376if [[ ${rootfs_partition} = "raw" ]]; then 377 sudo e2fsck -p -f "${disk}" || true 378else 379 rootfs_partition_start=$(partx -g -o START -s -n "${rootfs_partition}" "${disk}" | xargs) 380 rootfs_partition_end=$(partx -g -o END -s -n "${rootfs_partition}" "${disk}" | xargs) 381 rootfs_partition_num_sectors=$((${rootfs_partition_end} - ${rootfs_partition_start} + 1)) 382 rootfs_partition_offset=$((${rootfs_partition_start} * 512)) 383 rootfs_partition_tempfile2=$(mktemp) 384 dd if="${disk}" of="${rootfs_partition_tempfile2}" bs=512 skip=${rootfs_partition_start} count=${rootfs_partition_num_sectors} 385 /sbin/e2fsck -p -f "${rootfs_partition_tempfile2}" || true 386 dd if="${rootfs_partition_tempfile2}" of="${disk}" bs=512 seek=${rootfs_partition_start} count=${rootfs_partition_num_sectors} conv=fsync,notrunc 387 rm -f "${rootfs_partition_tempfile2}" 388 /sbin/e2fsck -fy "${disk}"?offset=${rootfs_partition_offset} || true 389fi 390if [[ -n "${system_partition}" ]]; then 391 system_partition_start=$(partx -g -o START -s -n "${system_partition}" "${disk}" | xargs) 392 system_partition_end=$(partx -g -o END -s -n "${system_partition}" "${disk}" | xargs) 393 system_partition_num_sectors=$((${system_partition_end} - ${system_partition_start} + 1)) 394 system_partition_offset=$((${system_partition_start} * 512)) 395 system_partition_size=$((${system_partition_num_sectors} * 512)) 396 system_partition_tempfile=$(mktemp) 397 dd if="${disk}" of="${system_partition_tempfile}" bs=512 skip=${system_partition_start} count=${system_partition_num_sectors} 398 /sbin/fsck.vfat -a "${system_partition_tempfile}" || true 399 dd if="${system_partition_tempfile}" of="${disk}" bs=512 seek=${system_partition_start} count=${system_partition_num_sectors} conv=fsync,notrunc 400 rm -f "${system_partition_tempfile}" 401fi 402 403# New workdir for the initrd extraction 404workdir="${tmpdir}/initrd" 405mkdir "${workdir}" 406chmod 0755 "${workdir}" 407sudo chown root:root "${workdir}" 408 409# Change into workdir to repack initramfs 410cd "${workdir}" 411 412# Process the initrd to remove kernel-specific metadata 413kernel_version=$(basename $(lz4 -lcd "${raw_initrd}" | sudo cpio -idumv 2>&1 | grep usr/lib/modules/ - | head -n1)) 414lz4 -lcd "${raw_initrd}" | sudo cpio -idumv 415sudo rm -rf usr/lib/modules 416sudo mkdir -p usr/lib/modules 417 418# Debian symlinks /usr/lib to /lib, but we'd prefer the other way around 419# so that it more closely matches what happens in Android initramfs images. 420# This enables 'cat ramdiskA.img ramdiskB.img >ramdiskC.img' to "just work". 421sudo rm -f lib 422sudo mv usr/lib lib 423sudo ln -s /lib usr/lib 424 425# Repack the ramdisk to the final output 426find * | sudo cpio -H newc -o --quiet | lz4 -lc9 >"${ramdisk}" 427 428# Pack another ramdisk with the combined artifacts, for boot testing 429cat "${ramdisk}" "${initramfs}" >"${initrd}" 430 431# Leave workdir to boot-test combined initrd 432cd - 433 434rootfs_partition_tempfile=$(mktemp) 435# Mount the new filesystem locally 436if [[ ${rootfs_partition} = "raw" ]]; then 437 sudo mount -o loop -t ext4 "${disk}" "${mount}" 438else 439 rootfs_partition_start=$(partx -g -o START -s -n "${rootfs_partition}" "${disk}" | xargs) 440 rootfs_partition_offset=$((${rootfs_partition_start} * 512)) 441 rootfs_partition_end=$(partx -g -o END -s -n "${rootfs_partition}" "${disk}" | xargs) 442 rootfs_partition_num_sectors=$((${rootfs_partition_end} - ${rootfs_partition_start} + 1)) 443 dd if="${disk}" of="${rootfs_partition_tempfile}" bs=512 skip=${rootfs_partition_start} count=${rootfs_partition_num_sectors} 444fi 445image_unmount2() { 446 sudo umount "${mount}" 447 raw_initrd_remove 448} 449if [[ ${rootfs_partition} = "raw" ]]; then 450 trap image_unmount2 EXIT 451fi 452 453# Embed the kernel and dtb images now, if requested 454if [[ ${rootfs_partition} = "raw" ]]; then 455 if [[ "${embed_kernel_initrd_dtb}" = "1" ]]; then 456 if [ -n "${dtb}" ]; then 457 sudo mkdir -p "${mount}/boot/dtb/${dtb_subdir}" 458 sudo cp -a "${dtb}" "${mount}/boot/dtb/${dtb_subdir}" 459 sudo chown -R root:root "${mount}/boot/dtb/${dtb_subdir}" 460 fi 461 sudo cp -a "${kernel}" "${mount}/boot/vmlinuz-${kernel_version}" 462 sudo chown root:root "${mount}/boot/vmlinuz-${kernel_version}" 463 fi 464 sudo cp -a "${SCRIPT_DIR}"/rootfs/cron-run-installer-script "${mount}/etc/cron.d/cron-run-installer-script" 465 if [ -e "${extradeb}" ]; then 466 sudo cp -a "${extradeb}" "${mount}/root/extradeb.tar.gz" 467 sudo chown root:root "${mount}/root/extradeb.tar.gz" 468 fi 469else 470 if [[ "${embed_kernel_initrd_dtb}" = "1" ]]; then 471 if [ -n "${dtb}" ]; then 472 e2mkdir -G 0 -O 0 "${rootfs_partition_tempfile}":"/boot/dtb/${dtb_subdir}" 473 e2cp -G 0 -O 0 "${dtb}" "${rootfs_partition_tempfile}":"/boot/dtb/${dtb_subdir}" 474 fi 475 e2cp -G 0 -O 0 "${kernel}" "${rootfs_partition_tempfile}":"/boot/vmlinuz-${kernel_version}" 476 fi 477 e2cp -G 0 -O 0 "${SCRIPT_DIR}"/rootfs/cron-run-installer-script "${rootfs_partition_tempfile}":"/etc/cron.d/cron-run-installer-script" 478 if [ -e "${extradeb}" ]; then 479 e2cp -G 0 -O 0 "${extradeb}" "${rootfs_partition_tempfile}":"/root/extradeb.tar.gz" 480 fi 481fi 482 483# Unmount the initial ramdisk 484if [[ ${rootfs_partition} = "raw" ]]; then 485 sudo umount "${mount}" 486else 487 rootfs_partition_start=$(partx -g -o START -s -n "${rootfs_partition}" "${disk}" | xargs) 488 rootfs_partition_end=$(partx -g -o END -s -n "${rootfs_partition}" "${disk}" | xargs) 489 rootfs_partition_num_sectors=$((${rootfs_partition_end} - ${rootfs_partition_start} + 1)) 490 dd if="${rootfs_partition_tempfile}" of="${disk}" bs=512 seek=${rootfs_partition_start} count=${rootfs_partition_num_sectors} conv=fsync,notrunc 491fi 492rm -f "${rootfs_partition_tempfile}" 493trap raw_initrd_remove EXIT 494 495# Boot test the new system and run stage 3 496${qemu} -machine "${machine}" -cpu "${cpu}" -m 2048 >&2 \ 497 -kernel "${kernel}" -initrd "${initrd}" -no-user-config -nodefaults \ 498 -no-reboot -display none -nographic -serial stdio -parallel none \ 499 -smp "${qemucpucores}",sockets="${qemucpucores}",cores=1,threads=1 \ 500 -object rng-random,id=objrng0,filename=/dev/urandom \ 501 -device virtio-rng-pci-non-transitional,rng=objrng0,id=rng0,max-bytes=1024,period=2000 \ 502 -drive file="${disk}",format=raw,if=none,aio=threads,id=drive-virtio-disk0 \ 503 -device virtio-blk-pci-non-transitional,scsi=off,drive=drive-virtio-disk0 \ 504 -chardev file,id=exitcode,path=exitcode \ 505 -device pci-serial,chardev=exitcode \ 506 -netdev user,id=usernet0,ipv6=off \ 507 -device virtio-net-pci-non-transitional,netdev=usernet0,id=net0 \ 508 -append "root=LABEL=ROOT installer_script=/root/${suite}.sh ${cmdline}" 509[[ -s exitcode ]] && exitcode=$(cat exitcode | tr -d '\r') || exitcode=2 510rm -f exitcode 511if [ "${exitcode}" != "0" ]; then 512 echo "Root filesystem finalization failed (err=${exitcode})" 513 exit "${exitcode}" 514fi 515 516# Fix up any issues from the unclean shutdown 517if [[ ${rootfs_partition} = "raw" ]]; then 518 sudo e2fsck -p -f "${disk}" || true 519else 520 rootfs_partition_start=$(partx -g -o START -s -n "${rootfs_partition}" "${disk}" | xargs) 521 rootfs_partition_end=$(partx -g -o END -s -n "${rootfs_partition}" "${disk}" | xargs) 522 rootfs_partition_num_sectors=$((${rootfs_partition_end} - ${rootfs_partition_start} + 1)) 523 rootfs_partition_offset=$((${rootfs_partition_start} * 512)) 524 rootfs_partition_tempfile2=$(mktemp) 525 dd if="${disk}" of="${rootfs_partition_tempfile2}" bs=512 skip=${rootfs_partition_start} count=${rootfs_partition_num_sectors} 526 /sbin/e2fsck -p -f "${rootfs_partition_tempfile2}" || true 527 dd if="${rootfs_partition_tempfile2}" of="${disk}" bs=512 seek=${rootfs_partition_start} count=${rootfs_partition_num_sectors} conv=fsync,notrunc 528 rm -f "${rootfs_partition_tempfile2}" 529 /sbin/e2fsck -fy "${disk}"?offset=${rootfs_partition_offset} || true 530fi 531if [[ -n "${system_partition}" ]]; then 532 system_partition_start=$(partx -g -o START -s -n "${system_partition}" "${disk}" | xargs) 533 system_partition_end=$(partx -g -o END -s -n "${system_partition}" "${disk}" | xargs) 534 system_partition_num_sectors=$((${system_partition_end} - ${system_partition_start} + 1)) 535 system_partition_offset=$((${system_partition_start} * 512)) 536 system_partition_size=$((${system_partition_num_sectors} * 512)) 537 system_partition_tempfile=$(mktemp) 538 dd if="${disk}" of="${system_partition_tempfile}" bs=512 skip=${system_partition_start} count=${system_partition_num_sectors} 539 /sbin/fsck.vfat -a "${system_partition_tempfile}" || true 540 dd if="${system_partition_tempfile}" of="${disk}" bs=512 seek=${system_partition_start} count=${system_partition_num_sectors} conv=fsync,notrunc 541 rm -f "${system_partition_tempfile}" 542fi 543 544# Mount the final disk image locally 545if [[ ${rootfs_partition} = "raw" ]]; then 546 sudo mount -o loop -t ext4 "${disk}" "${mount}" 547else 548 rootfs_partition_start=$(partx -g -o START -s -n "${rootfs_partition}" "${disk}" | xargs) 549 rootfs_partition_offset=$((${rootfs_partition_start} * 512)) 550 sudo mount -o loop,offset=${rootfs_partition_offset} -t ext4 "${disk}" "${mount}" 551fi 552image_unmount3() { 553 sudo umount "${mount}" 554 raw_initrd_remove 555} 556trap image_unmount3 EXIT 557 558# Fill the rest of the space with zeroes, to optimize compression 559sudo dd if=/dev/zero of="${mount}/sparse" bs=1M 2>/dev/null || true 560sudo rm -f "${mount}/sparse" 561 562echo "Debian ${suite} for ${arch} filesystem generated at '${disk}'." 563echo "Initial ramdisk generated at '${ramdisk}'." 564