1 /* 2 apfs.c -- parted support for apfs file systems 3 Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include <config.h> 20 21 #include <parted/parted.h> 22 #include <parted/debug.h> 23 #include <parted/endian.h> 24 25 #include "amiga.h" 26 #include "apfs.h" 27 28 #if ENABLE_NLS 29 # include <libintl.h> 30 # define _(String) dgettext (PACKAGE, String) 31 #else 32 # define _(String) (String) 33 #endif /* ENABLE_NLS */ 34 35 static int 36 _apfs_probe_root (uint32_t *block, uint32_t blocksize, uint32_t kind) { 37 if (PED_BE32_TO_CPU (block[0]) != kind) return 0; 38 return 1; 39 } 40 41 static PedGeometry* 42 _generic_apfs_probe (PedGeometry* geom, uint32_t kind) 43 { 44 uint32_t *block; 45 PedSector root; 46 struct PartitionBlock * part; 47 uint32_t blocksize = 1, reserved = 2, prealloc = 0; 48 49 PED_ASSERT (geom != NULL, return NULL); 50 PED_ASSERT (geom->dev != NULL, return NULL); 51 52 /* Finds the blocksize, prealloc and reserved values of the partition block */ 53 if (!(part = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { 54 ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 55 _("%s : Failed to allocate partition block\n"), __func__); 56 goto error_part; 57 } 58 if (amiga_find_part(geom, part) != NULL) { 59 prealloc = PED_BE32_TO_CPU (part->de_PreAlloc); 60 reserved = PED_BE32_TO_CPU (part->de_Reserved); 61 blocksize = PED_BE32_TO_CPU (part->de_SizeBlock) 62 * PED_BE32_TO_CPU (part->de_SectorPerBlock) / 128; 63 } 64 ped_free (part); 65 66 /* Test boot block */ 67 if (!(block = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { 68 ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 69 _("%s : Failed to allocate block\n"), __func__); 70 goto error_block; 71 } 72 if (!ped_device_read (geom->dev, block, geom->start, blocksize)) { 73 ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 74 _("%s : Couldn't read boot block %llu\n"), __func__, geom->start); 75 goto error; 76 } 77 if (PED_BE32_TO_CPU (block[0]) != kind) { 78 goto error; 79 } 80 81 /* Find and test the root block */ 82 root = geom->start+reserved*blocksize; 83 if (!ped_device_read (geom->dev, block, root, blocksize)) { 84 ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 85 _("%s : Couldn't read root block %llu\n"), __func__, root); 86 goto error; 87 } 88 if (_apfs_probe_root(block, blocksize, kind) == 1) { 89 ped_free(block); 90 return ped_geometry_duplicate (geom); 91 } 92 93 error: 94 ped_free (block); 95 error_block: 96 error_part: 97 return NULL; 98 } 99 100 static PedGeometry* 101 _apfs1_probe (PedGeometry* geom) { 102 return _generic_apfs_probe (geom, 0x50463101); 103 } 104 105 static PedGeometry* 106 _apfs2_probe (PedGeometry* geom) { 107 return _generic_apfs_probe (geom, 0x50463102); 108 } 109 110 static PedFileSystemOps _apfs1_ops = { 111 .probe = _apfs1_probe, 112 .clobber = NULL, 113 .open = NULL, 114 .create = NULL, 115 .close = NULL, 116 .check = NULL, 117 .resize = NULL, 118 .copy = NULL, 119 .get_create_constraint = NULL, 120 .get_copy_constraint = NULL, 121 .get_resize_constraint = NULL 122 }; 123 static PedFileSystemOps _apfs2_ops = { 124 .probe = _apfs2_probe, 125 .clobber = NULL, 126 .open = NULL, 127 .create = NULL, 128 .close = NULL, 129 .check = NULL, 130 .resize = NULL, 131 .copy = NULL, 132 .get_create_constraint = NULL, 133 .get_copy_constraint = NULL, 134 .get_resize_constraint = NULL 135 }; 136 137 #define APFS_BLOCK_SIZES ((int[2]){512, 0}) 138 139 PedFileSystemType _apfs1_type = { 140 .next = NULL, 141 .ops = &_apfs1_ops, 142 .name = "apfs1", 143 .block_sizes = APFS_BLOCK_SIZES 144 }; 145 PedFileSystemType _apfs2_type = { 146 .next = NULL, 147 .ops = &_apfs2_ops, 148 .name = "apfs2", 149 .block_sizes = APFS_BLOCK_SIZES 150 };