[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[EFI] partman-efi: add amd64/i386 support



Hi,

Here's where much of the EFI work has gone, adding code to deal with
x86 EFI systems. I've mainly merged code from Ubuntu here, but also
fixed a shell expansion bug I found in testing it. Be careful not to
destroy and create a new EFI system partition where one already
exists...

Depends on the libdebian-installer patch to add the "efi" subarch.

This also adds another translatable string
(partman-efi/too_small_efi). If we'd rather not make that kind of
change at this point, I think we can leave that part out for now.

-- 
Steve McIntyre, Cambridge, UK.                                steve@einval.com
"This dress doesn't reverse." -- Alden Spiess
mr diff: /home/steve/debian/d-i/d-i/packages/partman-efi
diff --git a/check.d/efi b/check.d/efi
index cf6f26f..29ce87f 100755
--- a/check.d/efi
+++ b/check.d/efi
@@ -7,6 +7,7 @@ fi
 . /lib/partman/lib/base.sh
 
 have_efi=no
+new_efi_size=
 
 # Is there at least one efi-partition?
 for dev in $DEVICES/*; do
@@ -16,17 +17,22 @@ for dev in $DEVICES/*; do
 	open_dialog PARTITIONS
 	while { read_line num id size type fs path name; [ "$id" ]; }; do
 		[ "$fs" != free ] || continue
-		partitions="$partitions $id,$num"
+		partitions="$partitions $id,$num,$size"
 	done
 	close_dialog
 
 	for part in $partitions; do
-		id=${part%,*}
-		num=${part#*,}
+		id=${part%%,*}
+		part=${part##*,}
+		num=${part%,*}
+		size=${part#*,}
 		[ -f $id/method ] || continue
 		method=$(cat $id/method)
 		if [ "$method" = efi ] && [ -f $id/bootable ]; then
 			have_efi=yes
+			if [ -f $id/format ] && [ -z "$new_efi_size" ]; then
+				new_efi_size="$size"
+			fi
 		fi
 	done
 done
@@ -40,4 +46,18 @@ if [ $have_efi = no ]; then
 	fi
 fi
 
+ARCH="$(archdetect)"
+
+# Experimentally-verified minimum size for a FAT32 filesystem created using
+# libparted.
+case $ARCH in
+    i386/*|amd64/*)
+	if [ "$new_efi_size" ] && longint_le "$new_efi_size" 34091007; then
+		db_input critical partman-efi/too_small_efi || true
+		db_go || true
+		exit 1
+	fi
+	;;
+esac
+
 exit 0
diff --git a/choose_method/efi/do_option b/choose_method/efi/do_option
index c3b799a..2f5a663 100755
--- a/choose_method/efi/do_option
+++ b/choose_method/efi/do_option
@@ -6,11 +6,18 @@ id=$3
 mkdir -p $dev/$id
 
 echo efi >$dev/$id/method
->$dev/$id/format
+# See comment in commit.d/format_efi.  We check again here to make the
+# confirm-changes screen less scary.
+if [ -f $dev/$id/detected_filesystem ]; then
+	rm -f $dev/$id/format
+else
+	>$dev/$id/format
+fi
 >$dev/$id/bootable
 >$dev/$id/efi_bootable
 
 rm -f $dev/$id/use_filesystem
 rm -f $dev/$id/filesystem
+rm -f $dev/$id/mountpoint
 
 exit 0
diff --git a/commit.d/format_efi b/commit.d/format_efi
index 20075f2..b93ba4b 100755
--- a/commit.d/format_efi
+++ b/commit.d/format_efi
@@ -2,6 +2,16 @@
 
 . /lib/partman/lib/base.sh
 
+ARCH="$(archdetect)"
+case $ARCH in
+    i386/*|amd64/*)
+	new_efi_fs=fat32
+	;;
+    *)
+	new_efi_fs=fat16
+	;;
+esac
+
 enable_swap
 for dev in $DEVICES/*; do
 	[ -d "$dev" ] || continue
@@ -18,13 +28,20 @@ for dev in $DEVICES/*; do
 		id=${part%,*}
 		num=${part#*,}
 		[ -f $id/method -a -f $id/format ] || continue
+		# Formatting an EFI System Partition that already has a
+		# filesystem on it is dangerous
+		# (https://bugs.launchpad.net/bugs/769669).  The least bad
+		# option seems to be to skip such partitions entirely.
+		if [ -f $id/detected_filesystem ]; then
+			continue
+		fi
 		method=$(cat $id/method)
 		if [ "$method" = efi ]; then
 			if [ -f $id/formatted ] && \
 			   [ $id/formatted -nt $id/method ]; then
 				continue
 			fi
-			log "Try to format EFI fat16 fs in $dev/$id"
+			log "Try to format EFI $new_efi_fs fs in $dev/$id"
 			template=partman-basicfilesystems/progress_formatting
 			open_dialog PARTITION_INFO $id
 			read_line x1 x2 x3 x4 x5 device x6
@@ -37,7 +54,7 @@ for dev in $DEVICES/*; do
 			db_subst $template PARTITION "$num"
 			db_subst $template DEVICE $(humandev $(cat device))
 			name_progress_bar $template
-			open_dialog CREATE_FILE_SYSTEM $id fat16
+			open_dialog CREATE_FILE_SYSTEM $id $new_efi_fs
 			read_line status
 			close_dialog
 			sync
diff --git a/debian/changelog b/debian/changelog
index 30667a4..ec395cf 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,16 @@
+partman-efi (27) unstable; urgency=low
+
+  * EFI development work, merging code from Ubuntu
+    + format EFI system partition using fat32 on x86/efi, leave fat16 on
+      ia64
+    + label appropriately
+    + check that the EFI system partition is big enough at creation time
+    + Don't format things that look like existing EFI system partitions,
+      reuse them instead
+    + fixed a bug in shell variable expansion in lib/partman/lib/base.sh
+
+ -- Steve McIntyre <93sam@debian.org>  Tue, 21 Aug 2012 23:22:01 +0100
+
 partman-efi (26) unstable; urgency=low
 
   * Team upload
diff --git a/debian/install b/debian/install
index e273175..7cd2a58 100644
--- a/debian/install
+++ b/debian/install
@@ -1 +1,2 @@
 parted_names lib/partman
+fstab.d lib/partman
diff --git a/debian/partman-efi.templates b/debian/partman-efi.templates
index d6bc63a..e48c997 100644
--- a/debian/partman-efi.templates
+++ b/debian/partman-efi.templates
@@ -35,4 +35,9 @@ Type: text
 # :sl5:
 _Description: EFI-fat16
 
-
+Template: partman-efi/too_small_efi
+Type: error
+# :sl5:
+_Description: EFI partition too small
+ EFI boot partitions on this architecture cannot be created with a size less
+ than 35 MB. Please make the EFI boot partition larger.
diff --git a/init.d/efi b/init.d/efi
index 6af77ce..3c5a7d2 100755
--- a/init.d/efi
+++ b/init.d/efi
@@ -1,25 +1,53 @@
 #!/bin/sh
 
-# This script sets method "efi" for all fat16 partitions that have the boot
-# flag set.
+# This script sets method "efi" for all fat16/fat32 partitions that
+# have the bootable flag set.
 
 # Give the kernel a chance to create /proc/efi if appropriate.
 modprobe efivars >/dev/null 2>&1 || true
 
-if [ ! -d /proc/efi ] && [ ! -d /sys/firmware/efi ]; then
-	exit 0
+if [ -d /proc/efi ] || [ -d /sys/firmware/efi ]; then
+	> /var/lib/partman/efi
+else
+	ARCH="$(archdetect)"
+	case $ARCH in
+	    i386/mac|amd64/mac)
+		# Intel Macs have an EFI partition, regardless of
+		# whether we're currently booted using BIOS
+		# compatibility or not (if we are, we won't be able to
+		# talk to EFI directly).
+		> /var/lib/partman/efi
+		;;
+	    *)
+		rm -f /var/lib/partman/efi
+		exit 0
+		;;
+	esac
 fi
 
 . /lib/partman/lib/base.sh
 
+gpt_efi_type=c12a7328-f81f-11d2-ba4b-00a0c93ec93b
+
 for dev in /var/lib/partman/devices/*; do
 	[ -d "$dev" ] || continue
 	cd $dev
+
+	open_dialog GET_LABEL_TYPE
+	read_line label_type
+	close_dialog
+
 	partitions=
 	open_dialog PARTITIONS
 	while { read_line num id size type fs path name; [ "$id" ]; }; do
 		if [ "$fs" = fat16 ]; then
 			partitions="$partitions $id"
+		elif [ "$fs" = fat32 ] && echo "$name" |
+                     grep -i "^EFI System Partition" >/dev/null; then
+			partitions="$partitions $id"
+		elif [ "$label_type" = gpt ] && \
+		     [ "$(blkid -o value -s PART_ENTRY_TYPE -p "$path" 2>/dev/null)" = "$gpt_efi_type" ]; then
+			partitions="$partitions $id"
 		fi
 	done
 	close_dialog
diff --git a/update.d/efi_sync_flag b/update.d/efi_sync_flag
index 53d73f6..149c64a 100755
--- a/update.d/efi_sync_flag
+++ b/update.d/efi_sync_flag
@@ -16,6 +16,8 @@ size=$4
 type=$5
 fs=$6
 path=$7
+shift; shift; shift; shift; shift; shift; shift
+name=$*
 
 cd $dev
 
@@ -37,6 +39,10 @@ while { read_line flag; [ "$flag" ]; }; do
 done
 close_dialog
 
+open_dialog USES_NAMES
+read_line uses_names
+close_dialog
+
 if [ "$method" = efi ] && [ ! -f $id/bootable ]; then
 	open_dialog SET_FLAGS $id
 	write_line "$flags"
@@ -45,6 +51,10 @@ if [ "$method" = efi ] && [ ! -f $id/bootable ]; then
 	close_dialog
 	>$id/bootable
 	>$id/efi_bootable
+	if [ "$uses_names" = yes ] && [ "$fs" = fat32 ]; then
+		open_dialog SET_NAME $id "EFI System Partition"
+		close_dialog
+	fi
 	RET=''
 elif [ "$method" != efi ] && [ -f $id/bootable ] && \
      [ -f $id/efi_bootable ]; then
@@ -54,4 +64,9 @@ elif [ "$method" != efi ] && [ -f $id/bootable ] && \
 	close_dialog
 	rm $id/bootable
 	rm $id/efi_bootable
+	if [ "$uses_names" = yes ] && [ "$fs" = fat32 ] && \
+	   [ "$name" = "EFI System Partition" ]; then
+		open_dialog SET_NAME ""
+		close_dialog
+	fi
 fi

mr diff: finished (1 ok)

Reply to: