mirror of
				https://gitlab.com/alemaire/image-specs.git
				synced 2025-01-17 17:48:20 +00:00 
			
		
		
		
	| @@ -66,6 +66,7 @@ steps: | |||||||
|   - apt: install |   - apt: install | ||||||
|     packages: |     packages: | ||||||
|     - ssh |     - ssh | ||||||
|  |     - parted | ||||||
|     - dosfstools |     - dosfstools | ||||||
|     # Contains /lib/firmware/brcm/brcmfmac43430-sdio.bin (required for WiFi). |     # Contains /lib/firmware/brcm/brcmfmac43430-sdio.bin (required for WiFi). | ||||||
|     - firmware-brcm80211 |     - firmware-brcm80211 | ||||||
|   | |||||||
| @@ -1,155 +1,9 @@ | |||||||
| #!/usr/bin/env perl | #!/bin/sh | ||||||
| # vim:ts=4:sw=4:et |  | ||||||
| # |  | ||||||
| # © 2017 Michael Stapelberg <stapelberg@debian.org> |  | ||||||
| # |  | ||||||
| # Extends the root partition and root file system to cover the entire remainder |  | ||||||
| # of the device. Requires the root file system to be a block device matching |  | ||||||
| # /.+p[0-9]$/, e.g. /dev/mmcblk0p2. |  | ||||||
| # |  | ||||||
| # Requires only perl-base (present on all Debian installations) |  | ||||||
|  |  | ||||||
| use strict; | roottmp=$(lsblk -l -o MAJ:MIN,MOUNTPOINT | grep '/$') | ||||||
| use Fcntl qw(:DEFAULT :seek); | rootpart=/dev/block/${roottmp% /} | ||||||
|  | rootdev=${rootpart%:*}:0 | ||||||
|  |  | ||||||
| ################################################################################ | parted -s $rootdev resizepart 2 100% | ||||||
| # Find the root device by looking at what is mounted on / |  | ||||||
| ################################################################################ |  | ||||||
|  |  | ||||||
| sub slurp { | resize2fs $rootpart | ||||||
|     my ($fn) = @_; |  | ||||||
|     open(my $fh, '<', $fn) |  | ||||||
|         or die qq|open($fn): $!|; |  | ||||||
|     local $/; |  | ||||||
|     <$fh>; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| my ($rootpart) = grep { $_ ne '' } map { /([^ ]+) \/ / && $1 } split("\n", slurp(</proc/mounts>)); |  | ||||||
| my $rootdev; |  | ||||||
| my $pno; |  | ||||||
| if ($rootpart =~ /^(.+)p([0-9])$/) { |  | ||||||
|     $rootdev = $1; |  | ||||||
|     $pno = int($2); |  | ||||||
| } else { |  | ||||||
|     die qq|root partition "$rootpart" unexpectedly does not end in p[0-9]|; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| ################################################################################ |  | ||||||
| # Get the size of the root block device in bytes |  | ||||||
| ################################################################################ |  | ||||||
|  |  | ||||||
| sub SYS_ioctl { 29; } # aarch64-specific |  | ||||||
| sub BLKGETSIZE64 { 2148012658; } |  | ||||||
|  |  | ||||||
| sysopen(my $root, $rootdev, O_RDWR) |  | ||||||
|     or die qq|sysopen($rootdev): $!|; |  | ||||||
|  |  | ||||||
| my $devsizep = pack("Q", ()); |  | ||||||
| $! = 0; |  | ||||||
| syscall(SYS_ioctl(), fileno($root), BLKGETSIZE64(), $devsizep) >= 0 |  | ||||||
|     or die qq|ioctl(BLKGETSIZE64): $!|; |  | ||||||
| my ($devsize) = unpack("Q", $devsizep); |  | ||||||
|  |  | ||||||
| ################################################################################ |  | ||||||
| # Read the partition table entry |  | ||||||
| ################################################################################ |  | ||||||
|  |  | ||||||
| sub boot_code { 446; } |  | ||||||
| sub partition_table_entry { 16; } |  | ||||||
| sub partition_table_start_offset { 8; } |  | ||||||
| sub partition_table_length_offset { 12; } |  | ||||||
| sub partition_count { 4; } |  | ||||||
| sub partition_signature_len { 2; } |  | ||||||
| sub tablelength { partition_table_entry() * partition_count() + partition_signature_len(); } |  | ||||||
|  |  | ||||||
| # The contents of $original_partition_table must be updated whenever the |  | ||||||
| # partition layout on the SD card image changes. |  | ||||||
| # This layout matches |  | ||||||
| # https://people.debian.org/~stapelberg/raspberrypi3/2017-10-08/2017-10-08-raspberry-pi-3-buster-PREVIEW.img.bz2 |  | ||||||
| my $original_partition_table = pack('H4' x (tablelength()/2), |  | ||||||
|     "0020", "2100", "0c3e", "1826", "0008", "0000", "0058", "0900", |  | ||||||
|     "003e", "1926", "833a", "2e8c", "0060", "0900", "0000", "1900", |  | ||||||
|     "0000", "0000", "0000", "0000", "0000", "0000", "0000", "0000", |  | ||||||
|     "0000", "0000", "0000", "0000", "0000", "0000", "0000", "0000", |  | ||||||
|     "55aa"); |  | ||||||
|  |  | ||||||
| sub check_orig_partition_table { |  | ||||||
|     my ($offset, $len, $bytes) = @_; |  | ||||||
|     sysseek($root, $offset, SEEK_SET) |  | ||||||
|         or die qq|sysseek($offset): $!|; |  | ||||||
|     my $buf; |  | ||||||
|     sysread($root, $buf, $len) |  | ||||||
|         or die qq|sysread(): $!|; |  | ||||||
|     if ($buf ne $bytes) { |  | ||||||
|         print "Partition table already modified\n"; |  | ||||||
|         exit 0; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| sub read_uint32_le { |  | ||||||
|     my ($offset) = @_; |  | ||||||
|     sysseek($root, $offset, SEEK_SET) |  | ||||||
|         or die qq|sysseek($offset): $!|; |  | ||||||
|     my $buf; |  | ||||||
|     sysread($root, $buf, 4) |  | ||||||
|         or die qq|sysread(): $!|; |  | ||||||
|     my ($val) = unpack("V", $buf); |  | ||||||
|     return $val; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # Ensure partition table has not been modified by the user. |  | ||||||
| check_orig_partition_table(boot_code(), tablelength(), $original_partition_table); |  | ||||||
|  |  | ||||||
| my $entry_offset = boot_code() + (partition_table_entry() * ($pno - 1)); |  | ||||||
| my $start     = 512 * read_uint32_le($entry_offset + partition_table_start_offset()); |  | ||||||
| my $oldlength = 512 * read_uint32_le($entry_offset + partition_table_length_offset()); |  | ||||||
| my $newlength = ($devsize - $start); |  | ||||||
| if ($oldlength == $newlength) { |  | ||||||
|     print "Partition $rootpart already at maximum size $newlength\n"; |  | ||||||
|     exit 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| ################################################################################ |  | ||||||
| # Change the partition length |  | ||||||
| ################################################################################ |  | ||||||
|  |  | ||||||
| sub write_uint32_le { |  | ||||||
|     my ($offset, $val) = @_; |  | ||||||
|     sysseek($root, $offset, SEEK_SET) |  | ||||||
|         or die qq|sysseek($offset): $!|; |  | ||||||
|     my $buf = pack("V", $val); |  | ||||||
|     syswrite($root, $buf, 4) |  | ||||||
|         or die qq|syswrite: $!|; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| print "Resizing partition $rootpart from $oldlength to $newlength bytes\n"; |  | ||||||
| write_uint32_le($entry_offset + partition_table_length_offset(), $newlength / 512); |  | ||||||
|  |  | ||||||
| ################################################################################ |  | ||||||
| # Tell linux about the new partition size using the BLKPG ioctl (BLKRRPART |  | ||||||
| # cannot be used when the device is mounted, even read-only). |  | ||||||
| ################################################################################ |  | ||||||
|  |  | ||||||
| sub BLKPG { 0x1269; } |  | ||||||
| sub BLKPG_RESIZE_PARTITION { 3; } |  | ||||||
|  |  | ||||||
| my $part = pack("q q i Z64 Z64", $start, $newlength, $pno, "devname", "volname"); |  | ||||||
| my $partb = "\x00" x length($part); |  | ||||||
| my $op = BLKPG_RESIZE_PARTITION(); |  | ||||||
| my $ioctl_arg = pack("i i i x4 p", $op, 0, length($part), $part); |  | ||||||
| $! = 0; |  | ||||||
| syscall(SYS_ioctl(), fileno($root), BLKPG(), $ioctl_arg) >= 0 |  | ||||||
|     or die "ioctl(BLKPG): $!"; |  | ||||||
|  |  | ||||||
| ################################################################################ |  | ||||||
| # Run resize2fs to enlarge the file system |  | ||||||
| ################################################################################ |  | ||||||
|  |  | ||||||
| # resize2fs requires the file system to be writeable. |  | ||||||
| my @remountcmd = ('mount', '-o', 'remount,rw', $rootpart); |  | ||||||
| system(@remountcmd) == 0 |  | ||||||
|     or die qq|system(| . join(" ", @remountcmd) . qq|): $!|; |  | ||||||
|  |  | ||||||
| my @resizecmd = ('resize2fs', "${rootpart}"); |  | ||||||
| exec { $resizecmd[0] } @resizecmd |  | ||||||
|     or die qq|exec(| . join(" ", @resizecmd) . qq|): $!|; |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Christian Schlüter
					Christian Schlüter