[parted-devel] [PATCH] delete driver partitions correctly from disks with mac label

Olaf Hering olh at suse.de
Sat Apr 8 14:22:52 UTC 2006


'parted $device rm 2' to remove a driver partition does not work correctly.

The partition block0 has an entry for the number of available driver partitions.
At the end, block0 has a list of block ranges and types of these drivers.
parted removes just the entries from the partition table, but it does not update the
list in block0. When MacOS 9 tries to access such a disk, it just crashes very early in boot.

This patch updates the block struct and related comments.
The check wether a partition is_driver or not did just match partition types.
But as shown in the list below, it would match partitions that do not hold drivers
listed in the block0 driver table. Also, the ->is_driver range check would trigger for
Apple_Driver_IOKit and Apple_FWDriver. But these partitions have no drivers.
Avoid the incorrect assert for these partition types.

        pdisk -l /dev/sda

        Partition map (with 512 byte blocks) on '/dev/sda'
         #:                type name                length   base     ( size )
         1: Apple_partition_map 'Apple          '       63 @ 1
         2:      Apple_Driver43*'Macintosh      '       54 @ 64
         3:      Apple_Driver43*'Macintosh      '       74 @ 118
         4:  Apple_Driver_IOKit 'Macintosh      '      512 @ 192
         5:       Apple_Patches 'Patch Partition'      512 @ 704
         6:           Apple_HFS 'untitled       ' 17848774 @ 1216     (  8.5G)
         7:          Apple_Free 'Extra          '       10 @ 17849990

        Device block size=512, Number of Blocks=17849999 (8.5G)
        DeviceType=0x0, DeviceId=0x0
        Drivers-
        1:  22 @ 64, type=0x1
        2:  36 @ 118, type=0xffff

        nectarine:~ # pdisk -l /dev/hdb

        Partition map (with 512 byte blocks) on '/dev/hdb'
         #:                type name                length   base     ( size )
         1: Apple_partition_map 'Apple          '       63 @ 1
         2:      Apple_Driver43*'Macintosh      '       56 @ 64
         3:      Apple_Driver43*'Macintosh      '       56 @ 120
         4:    Apple_Driver_ATA*'Macintosh      '       56 @ 176
         5:    Apple_Driver_ATA*'Macintosh      '       56 @ 232
         6:      Apple_FWDriver 'Macintosh      '      512 @ 288
         7:  Apple_Driver_IOKit 'Macintosh      '      512 @ 800
         8:       Apple_Patches 'Patch Partition'      512 @ 1312
         9:           Apple_HFS 'Untitled       '    66721 @ 1824     ( 32.6M)
        10:     Apple_UNIX_SVR2 'swap           '   800352 @ 68545    (390.8M)
        11:     Apple_UNIX_SVR2 'untitled       ' 52595423 @ 868897   ( 25.1G)

        Device block size=512, Number of Blocks=53464320 (25.5G)
        DeviceType=0x0, DeviceId=0x0
        Drivers-
        1:  23 @ 64, type=0x1
        2:  36 @ 120, type=0xffff
        3:  21 @ 176, type=0x701
        4:  34 @ 232, type=0xf8ff

        nectarine:~ # pdisk -l /dev/hdc

        Partition map (with 512 byte blocks) on '/dev/hdc'
         #:                type name               length   base    ( size )
         1: Apple_partition_map 'Apple          '      63 @ 1
         2:   Apple_Driver43_CD*'Macintosh      '     120 @ 196
         3:  Apple_Driver_ATAPI*'Macintosh      '      56 @ 316
         4:      Apple_Driver43 'Macintosh      '      14 @ 16
         5:  Apple_Driver_ATAPI*'Macintosh      '     120 @ 372
         6:       Apple_Patches 'Patch Partition'     512 @ 492
         7:           Apple_HFS 'Mac OS 9       ' 1310720 @ 1004    (640.0M)
         8:      Apple_Driver43 'Macintosh      '      19 @ 30
         9:          Apple_Free '               '   15284 @ 1311724 (  7.5M)

        Device block size=2048, Number of Blocks=331752 (648.0M)
        DeviceType=0x1, DeviceId=0x1
        Drivers-
        1:   5 @ 16, (20 at 64)  type=0x1
        2:  25 @ 49, (100 at 196)  type=0xffff
        3:   5 @ 79, (20 at 316)  type=0x701
        4:  26 @ 93, (104 at 372)  type=0xf8ff




---
 libparted/labels/mac.c |  110 +++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 97 insertions(+), 13 deletions(-)

Index: parted-mainline/libparted/labels/mac.c
===================================================================
--- parted-mainline.orig/libparted/labels/mac.c
+++ parted-mainline/libparted/labels/mac.c
@@ -113,20 +113,24 @@ typedef struct {
 	uint16_t	dev_id;		/* reserved */
 	uint32_t	data;		/* reserved */
 	uint16_t	driver_count;	/* # of driver descriptor entries */
-	uint32_t	start;		/* first driver's starting block */
-	uint16_t	size;		/* size of driver in blocks */
-	uint16_t	os_type;    	/* operating system type (MacOS = 1) */
-	uint16_t	specific[242];	/* info about additional drivers */
-	uint16_t	unused;		/* pad to 512 bytes */
+	uint8_t		driverlist[488]; /* info about available drivers */
+	uint16_t	padding[3];	/* pad to 512 bytes */
 } __attribute__ ((packed)) MacRawDisk;
 
 typedef struct {
+	uint32_t	block;		/* startblock in MacRawDisk->block_size units */
+	uint16_t	size;		/* size in 512 byte units */
+	uint16_t	type;		/* operating system type (MacOS = 1) */
+} __attribute__ ((packed)) MacDeviceDriver;
+
+typedef struct {
 	char		volume_name[33];	/* eg: "Games" */
 	char		system_name[33];	/* eg: "Apple_Unix_SVR2" */
 	char		processor_name[17];
 
 	int		is_boot;
 	int		is_driver;
+	int		has_driver;
 	int		is_root;
 	int		is_swap;
 	int		is_lvm;
@@ -151,6 +155,10 @@ typedef struct {
 	int		active_part_entry_count;	/* # real partitions */
 	int		free_part_entry_count;		/* # free space */
 	int		last_part_entry_num;		/* last entry number */
+
+	uint16_t	block_size;		/* physical sector size */
+	uint16_t	driver_count;
+	MacDeviceDriver	driverlist[1 + 60];	/* 488 bytes */
 } MacDiskData;
 
 static PedDiskType mac_disk_type;
@@ -275,6 +283,9 @@ mac_alloc (const PedDevice* dev)
 	mac_disk_data->active_part_entry_count = 0;
 	mac_disk_data->free_part_entry_count = 1;
 	mac_disk_data->last_part_entry_num = 1;
+	mac_disk_data->block_size = 0;
+	mac_disk_data->driver_count = 0;
+	memset(&mac_disk_data->driverlist[0], 0, sizeof(mac_disk_data->driverlist));
 
 	if (!_disk_add_part_map_entry (disk, 0))
 		goto error_free_disk;
@@ -410,6 +421,26 @@ _rawpart_is_driver (MacRawPartition* raw
 }
 
 static int
+_rawpart_has_driver (MacRawPartition* raw_part, MacDiskData* mac_disk_data)
+{
+	MacDeviceDriver *driverlist;
+	uint16_t i, bsz;
+	uint32_t driver_bs, driver_be, part_be;
+
+	driverlist = &mac_disk_data->driverlist[0];
+	bsz = mac_disk_data->block_size / 512;
+	for (i = 0; i < mac_disk_data->driver_count; i++) {
+		driver_bs = driverlist->block * bsz;
+		driver_be = driver_bs + driverlist->size;
+		part_be = raw_part->start_block + raw_part->block_count;
+		if (driver_bs >= raw_part->start_block && driver_be <= part_be)
+			return 1;
+		driverlist++;
+	}
+	return 0;
+}
+
+static int
 _rawpart_is_root (MacRawPartition* raw_part)
 {
 	if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2"))
@@ -523,6 +554,8 @@ _rawpart_analyse (MacRawPartition* raw_p
 
 	mac_part_data->is_boot = _rawpart_is_boot (raw_part);
 	mac_part_data->is_driver = _rawpart_is_driver (raw_part);
+	if (mac_part_data->is_driver)
+		mac_part_data->has_driver = _rawpart_has_driver(raw_part, mac_disk_data);
 	mac_part_data->is_root = _rawpart_is_root (raw_part);
 	mac_part_data->is_swap = _rawpart_is_swap (raw_part);
 	mac_part_data->is_lvm = _rawpart_is_lvm (raw_part);
@@ -560,7 +593,7 @@ _rawpart_analyse (MacRawPartition* raw_p
 		= PED_BE32_TO_CPU (raw_part->boot_count) * block_size;
 
 #ifndef DISCOVER_ONLY
-	if (mac_part_data->is_driver) {
+	if (mac_part_data->has_driver) {
 		if (mac_part_data->boot_region_length < part->geom.length) {
 			if (ped_exception_throw (
 				PED_EXCEPTION_ERROR,
@@ -725,6 +758,13 @@ mac_read (PedDisk* disk)
 	if (!ped_disk_delete_all (disk))
 		goto error;
 
+	if (raw_disk.driver_count && raw_disk.driver_count < 62) {
+		memcpy(&mac_disk_data->driverlist[0], &raw_disk.driverlist[0],
+				sizeof(mac_disk_data->driverlist));
+		mac_disk_data->driver_count = raw_disk.driver_count;
+		mac_disk_data->block_size = raw_disk.block_size;
+	}
+
 	for (num=1; num==1 || num <= last_part_entry_num; num++) {
 		if (!ped_device_read (disk->dev, &raw_part,
 				      num * ghost_size, 1))
@@ -818,9 +858,37 @@ _pad_raw_part (PedDisk* disk, int num, M
 	return 1;
 }
 
+static void
+_update_driver_count (MacRawPartition* part_map_entry,
+		      MacDiskData *mac_driverdata, const MacDiskData* mac_disk_data)
+{
+	uint16_t	i, count_orig, count_cur, bsz;
+	uint32_t	driver_bs, driver_be, part_be;
+
+	bsz = mac_disk_data->block_size / 512;
+	count_cur = mac_driverdata->driver_count;
+	count_orig = mac_disk_data->driver_count;
+	for (i = 0; i < count_orig; i++) {
+		driver_bs = mac_disk_data->driverlist[i].block * bsz;
+		driver_be = driver_bs + mac_disk_data->driverlist[i].size;
+		part_be = part_map_entry->start_block + part_map_entry->block_count;
+		if (driver_bs >= part_map_entry->start_block
+				&& driver_be <= part_be) {
+			mac_driverdata->driverlist[count_cur].block
+				= mac_disk_data->driverlist[i].block;
+			mac_driverdata->driverlist[count_cur].size
+				= mac_disk_data->driverlist[i].size;
+			mac_driverdata->driverlist[count_cur].type
+				= mac_disk_data->driverlist[i].type;
+			mac_driverdata->driver_count++;
+			break;
+		}
+	}
+}
+
 static int
 _generate_raw_part (PedDisk* disk, PedPartition* part,
-	       	    MacRawPartition* part_map)
+	       	    MacRawPartition* part_map, MacDiskData *mac_driverdata)
 {
 	MacDiskData*		mac_disk_data;
 	MacPartitionData*	mac_part_data;
@@ -844,9 +912,12 @@ _generate_raw_part (PedDisk* disk, PedPa
 	strcpy (part_map_entry->name, mac_part_data->volume_name);
 	strcpy (part_map_entry->type, mac_part_data->system_name);
 
-	if (mac_part_data->is_driver)
+	if (mac_part_data->is_driver) {
 		mac_part_data->boot_region_length = part->geom.length;
-	else
+		if (mac_part_data->has_driver)
+			_update_driver_count(part_map_entry, mac_driverdata,
+					mac_disk_data);
+	} else
 		mac_part_data->data_region_length = part->geom.length;
 	part_map_entry->data_count = PED_CPU_TO_BE32 (
 			mac_part_data->data_region_length / block_size);
@@ -942,7 +1013,7 @@ _get_first_empty_part_entry (PedDisk* di
 }
 
 static int
-write_block_zero (PedDisk* disk)
+write_block_zero (PedDisk* disk, MacDiskData* mac_driverdata)
 {
 	PedDevice*	dev = disk->dev;
 	MacRawDisk	raw_disk;
@@ -955,6 +1026,10 @@ write_block_zero (PedDisk* disk)
 	raw_disk.block_count
 		= PED_CPU_TO_BE32 (dev->length / (dev->sector_size / 512));
 
+	raw_disk.driver_count = mac_driverdata->driver_count;
+	memcpy(&raw_disk.driverlist[0], &mac_driverdata->driverlist[0],
+			sizeof(raw_disk.driverlist));
+
 	return ped_device_write (dev, &raw_disk, 0, 1);
 }
 
@@ -963,6 +1038,7 @@ mac_write (PedDisk* disk)
 {
 	MacRawPartition*	part_map;
 	MacDiskData*		mac_disk_data;
+	MacDiskData*		mac_driverdata;	/* updated driver list */
 	PedPartition*		part;
 	int			num;
 
@@ -978,10 +1054,15 @@ mac_write (PedDisk* disk)
 			goto error;
 	}
 
+	mac_driverdata = ped_malloc(sizeof(MacDiskData));
+	if (!mac_driverdata)
+		goto error;
+	memset (mac_driverdata, 0, sizeof(MacDiskData));
+
 	part_map = (MacRawPartition*)
 			ped_malloc (mac_disk_data->part_map_entry_count * 512);
 	if (!part_map)
-		goto error;
+		goto error_free_driverdata;
 	memset (part_map, 0, mac_disk_data->part_map_entry_count * 512);
 
 /* write (to memory) the "real" partitions */
@@ -989,7 +1070,7 @@ mac_write (PedDisk* disk)
 	     part = ped_disk_next_partition (disk, part)) {
 		if (!ped_partition_is_active (part))
 			continue;
-		if (!_generate_raw_part (disk, part, part_map))
+		if (!_generate_raw_part (disk, part, part_map, mac_driverdata))
 			goto error_free_part_map;
 	}
 
@@ -1014,10 +1095,12 @@ mac_write (PedDisk* disk)
 			       mac_disk_data->part_map_entry_count))
 		goto error_free_part_map;
 	ped_free (part_map);
-	return write_block_zero (disk);
+	return write_block_zero (disk, mac_driverdata);
 
 error_free_part_map:
 	ped_free (part_map);
+error_free_driverdata:
+	ped_free (mac_driverdata);
 error:
 	return 0;
 }
@@ -1046,6 +1129,7 @@ mac_partition_new (
 		mac_data->data_region_length = 0;
 		mac_data->boot_region_length = 0;
 		mac_data->is_driver = 0;
+		mac_data->has_driver = 0;
 		mac_data->is_boot = 0;
 		mac_data->is_root = 0;
 		mac_data->is_swap = 0;



More information about the parted-devel mailing list