summaryrefslogtreecommitdiffstats
path: root/debian/patches/freebsd-ufs.patch
blob: 2484d07e811c62b107dfd5fdafe0f7d42d18a1a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
From 1bb66d74adb068f467668aa6f2cd36775cb63fee Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Fri, 28 Mar 2014 17:09:46 +0000
Subject: Add FreeBSD UFS support

This patch adds support for detection of FreeBSD UFS file systems and
creation of the partition on DOS and GPT labels. It doesn't use the
system of slices used by default on FreeBSD and places the partition
directly in the dos label. This is something supported by the FreeBSD
kernel, and the default on Debian GNU/kFreeBSD. Even on plain FreeBSD,
some persons prefer to not use slices.

This patch is used by debian-installer on Debian GNU/kFreeBSD for some
months already.

Last-Update: 2023-06-12

Patch-Name: freebsd-ufs.patch
---
 libparted/fs/ufs/ufs.c     | 103 ++++++++++++++++++++++++++++++++++---
 libparted/labels/dos.c     |   3 ++
 libparted/labels/gpt.c     |   9 ++++
 tests/Makefile.am          |   1 +
 tests/t2500-freebsd-ufs.sh |  44 ++++++++++++++++
 5 files changed, 153 insertions(+), 7 deletions(-)
 create mode 100644 tests/t2500-freebsd-ufs.sh

diff --git a/libparted/fs/ufs/ufs.c b/libparted/fs/ufs/ufs.c
index d2bf4214..08ed5603 100644
--- a/libparted/fs/ufs/ufs.c
+++ b/libparted/fs/ufs/ufs.c
@@ -45,6 +45,7 @@
 #define UFS_MAGIC_LFN	0x00095014
 #define UFS_MAGIC_FEA	0x00195612
 #define UFS_MAGIC_4GB	0x05231994
+#define UFS2_MAGIC	0x19540119
 
 struct __attribute__ ((packed)) ufs_csum {
 	uint32_t	cs_ndir;	/* number of directories */
@@ -129,13 +130,50 @@ struct __attribute__ ((packed)) ufs_super_block {
 	int8_t		fs_clean;	/* file system is clean flag */
 	int8_t		fs_ronly;	/* mounted read-only flag */
 	int8_t		fs_flags;	/* currently unused flag */
-	int8_t		fs_fsmnt[UFS_MAXMNTLEN];	/* name mounted on */
-/* these fields retain the current block allocation info */
-	uint32_t	fs_cgrotor;	/* last cg searched */
-	uint32_t	fs_csp[UFS_MAXCSBUFS];	/* list of fs_cs info buffers */
-	uint32_t	fs_maxcluster;
-	uint32_t	fs_cpc;		/* cyl per cycle in postbl */
-	uint16_t	fs_opostbl[16][8];	/* old rotation block list head */
+	union {
+		struct {
+			int8_t		fs_fsmnt[UFS_MAXMNTLEN];	/* name mounted on */
+			/* these fields retain the current block allocation info */
+			uint32_t	fs_cgrotor;	/* last cg searched */
+			uint32_t	fs_csp[UFS_MAXCSBUFS];	/* list of fs_cs info buffers */
+			uint32_t	fs_maxcluster;
+			uint32_t	fs_cpc;		/* cyl per cycle in postbl */
+			uint16_t	fs_opostbl[16][8];	/* old rotation block list head */
+		} fs_u1;
+		struct {
+			int8_t		fs_fsmnt[468];
+			uint8_t		fs_volname[32];
+			uint64_t	fs_swuid;
+			int32_t		fs_pad;
+			uint32_t	fs_cgrotor;
+			uint32_t	fs_ocsp[28];
+			uint32_t	fs_contigdirs;
+			uint32_t	fs_csp;
+			uint32_t	fs_maxcluster;
+			uint32_t	fs_active;
+			int32_t		fs_old_cpc;
+			int32_t		fs_maxbsize;
+			int64_t		fs_sparecon64[17];
+			int64_t		fs_sblockloc;
+			struct ufs2_csum_total {
+				uint64_t	cs_ndir;
+				uint64_t	cs_nbfree;
+				uint64_t	cs_nifree;
+				uint64_t	cs_nffree;
+				uint64_t	cs_numclusters;
+				uint64_t	cs_spare[3];
+			} fs_cstotal;
+			struct ufs_timeval {
+				int32_t	 tv_sec;
+				int32_t	 tv_usec;
+			} fs_time;
+			int64_t		fs_size;
+			int64_t		fs_dsize;
+			uint64_t	fs_csaddr;
+			int64_t		fs_pendingblocks;
+			int32_t		fs_pendinginodes;
+		} __attribute__((packed)) fs_u2;
+	} fs_u11;
 	union {
 		struct {
 			int32_t		fs_sparecon[53];/* reserved for future constants */
@@ -244,6 +282,45 @@ ufs_probe_hp (PedGeometry* geom)
 	return NULL;
 }
 
+static PedGeometry*
+ufs_probe_freebsd (PedGeometry* geom)
+{
+	int offsets[] = { 0, 16, 128, 512 };
+	char *buf = alloca (3 * geom->dev->sector_size);
+	struct ufs_super_block *sb;
+	PedSector block_size;
+	PedSector block_count;
+	int i;
+
+	if (geom->length < 5)
+		return 0;
+
+	/* The UFS superblock could be on four different positions */
+	for (i = 0; i < 4; i++) {
+		if (!ped_geometry_read (geom, buf, offsets[i], 3))
+			return 0;
+
+		sb = (struct ufs_super_block *)buf;
+
+		/* Little endian is more likely on FreeBSD boxes */
+		if (PED_LE32_TO_CPU(sb->fs_magic) == UFS2_MAGIC) {
+			block_size = PED_LE32_TO_CPU(sb->fs_fsize) / geom->dev->sector_size;
+			block_count = PED_LE32_TO_CPU(sb->fs_u11.fs_u2.fs_size);
+			return ped_geometry_new (geom->dev, geom->start,
+						 block_size * block_count);
+		}
+
+		/* Then try big endian */
+		if (PED_BE32_TO_CPU(sb->fs_magic) == UFS2_MAGIC) {
+			block_size = PED_BE32_TO_CPU(sb->fs_fsize) / geom->dev->sector_size;
+			block_count = PED_BE32_TO_CPU(sb->fs_u11.fs_u2.fs_size);
+			return ped_geometry_new (geom->dev, geom->start,
+						 block_size * block_count);
+		}
+	}
+	return NULL;
+}
+
 static PedFileSystemOps ufs_ops_sun = {
 	probe:		ufs_probe_sun,
 };
@@ -252,6 +329,10 @@ static PedFileSystemOps ufs_ops_hp = {
 	probe:		ufs_probe_hp,
 };
 
+static PedFileSystemOps ufs_ops_freebsd = {
+	probe:		ufs_probe_freebsd,
+};
+
 static PedFileSystemType ufs_type_sun = {
 	next:	NULL,
 	ops:	&ufs_ops_sun,
@@ -264,6 +345,12 @@ static PedFileSystemType ufs_type_hp = {
 	name:   "hp-ufs",
 };
 
+static PedFileSystemType ufs_type_freebsd_ufs = {
+	next:   NULL,
+	ops:    &ufs_ops_freebsd,
+	name:   "freebsd-ufs"
+};
+
 void
 ped_file_system_ufs_init ()
 {
@@ -271,11 +358,13 @@ ped_file_system_ufs_init ()
 
 	ped_file_system_type_register (&ufs_type_sun);
 	ped_file_system_type_register (&ufs_type_hp);
+	ped_file_system_type_register (&ufs_type_freebsd_ufs);
 }
 
 void
 ped_file_system_ufs_done ()
 {
+	ped_file_system_type_unregister (&ufs_type_freebsd_ufs);
 	ped_file_system_type_unregister (&ufs_type_hp);
 	ped_file_system_type_unregister (&ufs_type_sun);
 }
diff --git a/libparted/labels/dos.c b/libparted/labels/dos.c
index 256f365d..95737d56 100644
--- a/libparted/labels/dos.c
+++ b/libparted/labels/dos.c
@@ -89,6 +89,7 @@ static const char MBR_BOOT_CODE[] = {
 #define PARTITION_IRST		0x84
 #define PARTITION_LINUX_EXT	0x85
 #define PARTITION_LINUX_LVM	0x8e
+#define PARTITION_FREEBSD_UFS	0xa5
 #define PARTITION_HFS		0xaf
 #define PARTITION_SUN_UFS	0xbf
 #define PARTITION_DELL_DIAG	0xde
@@ -1610,6 +1611,8 @@ msdos_partition_set_system (PedPartition* part,
 		dos_data->system = PARTITION_UDF;
 	else if (!strcmp (fs_type->name, "sun-ufs"))
 		dos_data->system = PARTITION_SUN_UFS;
+	else if (!strcmp (fs_type->name, "freebsd-ufs"))
+		dos_data->system = PARTITION_FREEBSD_UFS;
 	else if (is_linux_swap (fs_type->name))
 		dos_data->system = PARTITION_LINUX_SWAP;
 	else
diff --git a/libparted/labels/gpt.c b/libparted/labels/gpt.c
index 780fb705..130b9bd1 100644
--- a/libparted/labels/gpt.c
+++ b/libparted/labels/gpt.c
@@ -169,6 +169,10 @@ typedef struct
     ((efi_guid_t) { PED_CPU_TO_LE32 (0x933ac7e1), PED_CPU_TO_LE16 (0x2eb4), \
                     PED_CPU_TO_LE16 (0x4f13), 0xb8, 0x44, \
                     { 0x0e, 0x14, 0xe2, 0xae, 0xf9, 0x15 }})
+#define PARTITION_FREEBSD_UFS_GUID \
+    ((efi_guid_t) { PED_CPU_TO_LE32 (0x516e7cb6), PED_CPU_TO_LE16 (0x6ecf), \
+                    PED_CPU_TO_LE16 (0x11d6), 0x8f, 0xf8, \
+                    { 0x00, 0x02, 0x2d, 0x09, 0x71, 0x2b }})
 
 struct flag_uuid_mapping_t
 {
@@ -1490,6 +1494,11 @@ gpt_partition_set_system (PedPartition *part,
           gpt_part_data->type = PARTITION_SWAP_GUID;
           return 1;
         }
+      if (strstr (fs_type->name, "freebsd-ufs"))
+        {
+          gpt_part_data->type = PARTITION_FREEBSD_UFS_GUID;
+          return 1;
+        }
     }
 
   gpt_part_data->type = PARTITION_LINUX_DATA_GUID;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index fa27b44d..da093119 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -57,6 +57,7 @@ TESTS = \
   t2320-dos-extended-noclobber.sh \
   t2400-dos-hfs-partition-type.sh \
   t2410-dos-udf-partition-type.sh \
+  t2500-freebsd-ufs.sh \
   t2500-probe-corrupt-hfs.sh \
   t3000-resize-fs.sh \
   t3200-resize-partition.sh \
diff --git a/tests/t2500-freebsd-ufs.sh b/tests/t2500-freebsd-ufs.sh
new file mode 100644
index 00000000..5a46263d
--- /dev/null
+++ b/tests/t2500-freebsd-ufs.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+# Probe FreeBSD UFS file system
+
+# Copyright (C) 2010 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if test "$VERBOSE" = yes; then
+  set -x
+  parted --version
+fi
+
+: ${srcdir=.}
+. $srcdir/t-lib.sh
+require_512_byte_sector_size_
+
+dev=loop-file
+ss=$sector_size_
+n_sectors=8000
+
+fail=0
+
+( type mkfs.ufs ) >/dev/null 2>&1 || skip_test_ "no freebsd-ufs support"
+
+# create a freebsd-ufs file system
+dd if=/dev/zero of=$dev bs=1024 count=4096 >/dev/null || fail=1
+mkfs.ufs `pwd`/$dev >/dev/null || fail=1
+
+# probe the freebsd-ufs file system
+parted -m -s $dev u s print >out 2>&1 || fail=1
+grep '^1:.*:freebsd-ufs::;$' out || fail=1
+
+Exit $fail