1 1.14 andvar /* $NetBSD: md.c,v 1.14 2025/07/29 19:07:53 andvar Exp $ */ 2 1.1 dholland 3 1.1 dholland /* 4 1.1 dholland * Copyright 1997 Piermont Information Systems Inc. 5 1.1 dholland * All rights reserved. 6 1.1 dholland * 7 1.1 dholland * Based on code written by Philip A. Nelson for Piermont Information 8 1.1 dholland * Systems Inc. 9 1.1 dholland * 10 1.1 dholland * Redistribution and use in source and binary forms, with or without 11 1.1 dholland * modification, are permitted provided that the following conditions 12 1.1 dholland * are met: 13 1.1 dholland * 1. Redistributions of source code must retain the above copyright 14 1.1 dholland * notice, this list of conditions and the following disclaimer. 15 1.1 dholland * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 dholland * notice, this list of conditions and the following disclaimer in the 17 1.1 dholland * documentation and/or other materials provided with the distribution. 18 1.1 dholland * 3. The name of Piermont Information Systems Inc. may not be used to endorse 19 1.1 dholland * or promote products derived from this software without specific prior 20 1.1 dholland * written permission. 21 1.1 dholland * 22 1.1 dholland * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' 23 1.1 dholland * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.1 dholland * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.1 dholland * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE 26 1.1 dholland * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 1.1 dholland * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 1.1 dholland * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 1.1 dholland * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 1.1 dholland * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 1.1 dholland * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 32 1.1 dholland * THE POSSIBILITY OF SUCH DAMAGE. 33 1.1 dholland */ 34 1.1 dholland 35 1.1 dholland /* md.c -- mac68k machine specific routines */ 36 1.1 dholland 37 1.1 dholland #include <stdio.h> 38 1.1 dholland #include <util.h> 39 1.1 dholland #include <unistd.h> 40 1.1 dholland #include <fcntl.h> 41 1.1 dholland #include <sys/ioctl.h> 42 1.1 dholland #include <sys/utsname.h> 43 1.1 dholland #include <machine/int_fmtio.h> 44 1.1 dholland 45 1.1 dholland #include "defs.h" 46 1.1 dholland #include "md.h" 47 1.1 dholland #include "msg_defs.h" 48 1.1 dholland #include "menu_defs.h" 49 1.1 dholland 50 1.1 dholland static int stricmp(const char *c1, const char *c2); 51 1.1 dholland static void setpartition(struct apple_part_map_entry *, char *, int); 52 1.1 dholland static int getFreeLabelEntry(char *); 53 1.1 dholland static char *getFstype(struct apple_part_map_entry *, int, char *); 54 1.1 dholland static char *getUse(struct apple_part_map_entry *, int, char *); 55 1.1 dholland static char *getName(struct apple_part_map_entry *, int, char *); 56 1.1 dholland static int findStdType(int, char *, int, int *, int); 57 1.1 dholland static int check_for_errors(void); 58 1.1 dholland static int edit_diskmap(void); 59 1.1 dholland #ifdef MD_DEBUG_SORT_MERGE 60 1.1 dholland static int md_debug_dump(char *); 61 1.1 dholland #endif 62 1.1 dholland 63 1.1 dholland int blk_size; 64 1.1 dholland 65 1.1 dholland MAP_TYPE map_types[] = { 66 1.1 dholland {MAP_RESERVED, APPLE_PART_TYPE_DRIVER}, 67 1.1 dholland {MAP_RESERVED, APPLE_PART_TYPE_DRIVER43}, 68 1.1 dholland {MAP_RESERVED, APPLE_PART_TYPE_DRIVERATA}, 69 1.1 dholland {MAP_RESERVED, APPLE_PART_TYPE_FWB_COMPONENT}, 70 1.1 dholland {MAP_MACOS, APPLE_PART_TYPE_MAC}, 71 1.1 dholland {MAP_NETBSD, APPLE_PART_TYPE_NETBSD}, 72 1.1 dholland {MAP_RESERVED, APPLE_PART_TYPE_PARTMAP}, 73 1.1 dholland {MAP_OTHER, APPLE_PART_TYPE_SCRATCH}, 74 1.1 dholland {MAP_NETBSD, APPLE_PART_TYPE_UNIX}, 75 1.1 dholland {MAP_EOL, NULL} 76 1.1 dholland }; 77 1.1 dholland 78 1.1 dholland MAP map = {0, 0, 0, 0, 0, 0, 0, 0, {0}, NULL}; 79 1.1 dholland 80 1.1 dholland struct apple_part_map_entry new_map[] = 81 1.1 dholland { 82 1.1 dholland { APPLE_PART_MAP_ENTRY_MAGIC, 0xa5a5, 6, 1, NEW_MAP_SIZE & 0x7e, 83 1.1 dholland "Apple", "Apple_Partition_Map", 0, NEW_MAP_SIZE, 0x37, 84 1.1 dholland 0, 0, 0, 0, 0, 0, 0, {0}, {0}, {0}}, 85 1.1 dholland { APPLE_PART_MAP_ENTRY_MAGIC, 0, 6, 64, 32, 86 1.1 dholland "Macintosh", "Apple_Driver", 0, 0, 0x37, 87 1.1 dholland 0, 0, 0, 0, 0, 0, 0, {0}, {0}, {0}}, 88 1.1 dholland { APPLE_PART_MAP_ENTRY_MAGIC, 0, 6, 96, 64, 89 1.1 dholland "Macintosh", "Apple_Driver43", 0, 0, 0x37, 90 1.1 dholland 0, 0, 0, 0, 0, 0, 0, {0}, {0}, {0}}, 91 1.1 dholland { APPLE_PART_MAP_ENTRY_MAGIC, 0, 6, 160, 64, 92 1.1 dholland "Macintosh", "Apple_Driver_ATA", 0, 0, 0x37, 93 1.1 dholland 0, 0, 0, 0, 0, 0, 0, {0}, {0}, {0}}, 94 1.1 dholland { APPLE_PART_MAP_ENTRY_MAGIC, 0, 6, 224, 4096, 95 1.1 dholland "untitled", "Apple_HFS", 0, 0, 0x37, 96 1.1 dholland 0, 0, 0, 0, 0, 0, 0, {0}, {0}, {0}}, 97 1.1 dholland { APPLE_PART_MAP_ENTRY_MAGIC, 0, 6,4320, 0, 98 1.1 dholland "untitled", "Apple_Free", 0, 0, 0x37, 99 1.1 dholland 0, 0, 0, 0, 0, 0, 0, {0}, {0}, {0}} 100 1.1 dholland }; 101 1.1 dholland 102 1.1 dholland void 103 1.1 dholland md_init(void) 104 1.1 dholland { 105 1.1 dholland } 106 1.1 dholland 107 1.1 dholland void 108 1.1 dholland md_init_set_status(int flags) 109 1.1 dholland { 110 1.1 dholland struct utsname instsys; 111 1.1 dholland 112 1.1 dholland (void)flags; 113 1.1 dholland 114 1.1 dholland /* 115 1.1 dholland * Get the name of the Install Kernel we are running under and 116 1.1 dholland * enable the installation of the corresponding GENERIC kernel. 117 1.1 dholland * 118 1.1 dholland * Note: In md.h the two kernels are disabled. If they are 119 1.1 dholland * enabled there the logic here needs to be switched. 120 1.1 dholland */ 121 1.1 dholland uname(&instsys); 122 1.1 dholland if (strstr(instsys.version, "(INSTALLSBC)")) 123 1.1 dholland /* 124 1.1 dholland * Running the SBC Installation Kernel, so enable GENERICSBC 125 1.1 dholland */ 126 1.1 dholland set_kernel_set(SET_KERNEL_2); 127 1.1 dholland else 128 1.1 dholland /* 129 1.1 dholland * Running the GENERIC Installation Kernel, so enable GENERIC 130 1.1 dholland */ 131 1.1 dholland set_kernel_set(SET_KERNEL_1); 132 1.1 dholland } 133 1.1 dholland 134 1.6 martin bool 135 1.6 martin md_get_info(struct install_partition_desc *install) 136 1.1 dholland { 137 1.1 dholland struct disklabel disklabel; 138 1.1 dholland int fd, i; 139 1.1 dholland char dev_name[100]; 140 1.1 dholland struct apple_part_map_entry block; 141 1.1 dholland 142 1.1 dholland snprintf(dev_name, sizeof(dev_name), "/dev/r%s%c", 143 1.2 martin pm->diskdev, 'a' + getrawpartition()); 144 1.1 dholland 145 1.1 dholland /* 146 1.1 dholland * Open the disk as a raw device 147 1.1 dholland */ 148 1.1 dholland fd = open(dev_name, O_RDONLY, 0); 149 1.1 dholland if (fd < 0) { 150 1.1 dholland endwin(); 151 1.1 dholland fprintf (stderr, "Can't open %s\n", dev_name); 152 1.1 dholland exit(1); 153 1.1 dholland } 154 1.1 dholland /* 155 1.1 dholland * Try to get the default disklabel info for the device 156 1.1 dholland */ 157 1.1 dholland if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) { 158 1.1 dholland endwin(); 159 1.1 dholland fprintf (stderr, "Can't read disklabel on %s\n", dev_name); 160 1.1 dholland close(fd); 161 1.1 dholland exit(1); 162 1.1 dholland } 163 1.1 dholland /* 164 1.1 dholland * Get the disk parameters from the disk driver. It should have 165 1.13 andvar * obtained them by querying the disk itself. 166 1.1 dholland */ 167 1.1 dholland blk_size = disklabel.d_secsize; 168 1.2 martin pm->dlcyl = disklabel.d_ncylinders; 169 1.2 martin pm->dlhead = disklabel.d_ntracks; 170 1.2 martin pm->dlsec = disklabel.d_nsectors; 171 1.1 dholland /* 172 1.1 dholland * Just in case, initialize the structures we'll need if we 173 1.1 dholland * need to completely initialize the disk. 174 1.1 dholland */ 175 1.2 martin pm->dlsize = disklabel.d_secperunit; 176 1.5 dholland /* 177 1.5 dholland * XXX this code is broken: it accesses off the end of new_map[], 178 1.5 dholland * because NEW_MAP_SIZE is substantially larger than the number of 179 1.5 dholland * entries in new_map[]. Based on the description of struct 180 1.5 dholland * apple_part_map_entry in sys/bootblock.h, and the usage of it in 181 1.5 dholland * new_map[], NEW_MAP_SIZE is expected to be a block count, not an 182 1.5 dholland * entry count. As far I can tell the logic here is just wrong; it 183 1.5 dholland * needs someone with platform knowledge to sort it out. 184 1.5 dholland * 185 1.5 dholland * Note that nothing uses the data this writes into new_map[] so 186 1.5 dholland * disabling it should have no adverse consequences. 187 1.5 dholland * 188 1.5 dholland * - dholland 20160530 189 1.5 dholland */ 190 1.5 dholland #if 0 /* XXX broken */ 191 1.1 dholland for (i=0;i<NEW_MAP_SIZE;i++) { 192 1.1 dholland if (i > 0) 193 1.1 dholland new_map[i].pmPyPartStart = new_map[i-1].pmPyPartStart + 194 1.1 dholland new_map[i-1].pmPartBlkCnt; 195 1.1 dholland new_map[i].pmDataCnt = new_map[i].pmPartBlkCnt; 196 1.1 dholland if (new_map[i].pmPartBlkCnt == 0) { 197 1.2 martin new_map[i].pmPartBlkCnt = pm->dlsize; 198 1.2 martin new_map[i].pmDataCnt = pm->dlsize; 199 1.1 dholland break; 200 1.1 dholland } 201 1.2 martin pm->dlsize -= new_map[i].pmPartBlkCnt; 202 1.1 dholland } 203 1.5 dholland #endif /* 0 - broken */ 204 1.2 martin pm->dlsize = disklabel.d_secperunit; 205 1.1 dholland #if 0 206 1.7 christos msg_fmt_display(MSG_dldebug, "%d%d%d%d%d", 207 1.7 christos blk_size, pm->dlcyl, pm->dlhead, pm->dlsec, pm->dlsize); 208 1.1 dholland process_menu(MENU_ok, NULL); 209 1.1 dholland #endif 210 1.1 dholland map.size = 0; 211 1.1 dholland /* 212 1.1 dholland * Verify the disk has been initialized for MacOS use by checking 213 1.1 dholland * to see if the disk have a Boot Block 214 1.1 dholland */ 215 1.1 dholland if (lseek(fd, (off_t)0 * blk_size, SEEK_SET) < 0 || 216 1.1 dholland read(fd, &block, sizeof(block)) - sizeof(block) != 0 || 217 1.1 dholland block.pmSig != 0x4552) { 218 1.1 dholland process_menu(MENU_nodiskmap, NULL); 219 1.1 dholland } 220 1.1 dholland else { 221 1.1 dholland /* 222 1.1 dholland * Scan for the Partition Map entry that describes the Partition 223 1.1 dholland * Map itself. We need to know the number of blocks allocated 224 1.1 dholland * to it and the number currently in use. 225 1.1 dholland */ 226 1.1 dholland for (i=0;i<MAXMAXPARTITIONS;i++) { 227 1.1 dholland lseek(fd, (off_t)(i+1) * blk_size, SEEK_SET); 228 1.1 dholland read(fd, &block, sizeof(block)); 229 1.1 dholland if (stricmp("Apple_partition_map", (char *)block.pmPartType) == 0) { 230 1.1 dholland map.size = block.pmPartBlkCnt; 231 1.1 dholland map.in_use_cnt = block.pmMapBlkCnt; 232 1.1 dholland map.blk = (struct apple_part_map_entry *)malloc(map.size * blk_size); 233 1.1 dholland break; 234 1.1 dholland } 235 1.1 dholland } 236 1.1 dholland lseek(fd, (off_t)1 * blk_size, SEEK_SET); 237 1.1 dholland read(fd, map.blk, map.size * blk_size); 238 1.1 dholland } 239 1.1 dholland close(fd); 240 1.1 dholland 241 1.1 dholland return edit_diskmap(); 242 1.1 dholland } 243 1.1 dholland 244 1.1 dholland /* 245 1.1 dholland * md back-end code for menu-driven BSD disklabel editor. 246 1.1 dholland */ 247 1.10 martin int 248 1.6 martin md_make_bsd_partitions(struct install_partition_desc *install) 249 1.1 dholland { 250 1.9 martin int i, j, rv; 251 1.1 dholland EBZB *bzb; 252 1.9 martin struct disk_part_info info; 253 1.9 martin uint fs_type; 254 1.9 martin const char *mountpoint; 255 1.9 martin part_id pid; 256 1.9 martin size_t ndx; 257 1.1 dholland 258 1.1 dholland /* 259 1.1 dholland * Scan for any problems and report them before continuing. 260 1.1 dholland * The user can abort installation and we'll take them back 261 1.1 dholland * to the main menu; continue ignoring the warnings, or 262 1.1 dholland * ask to reedit the Disk Partition Map. 263 1.1 dholland */ 264 1.1 dholland while (1) { 265 1.1 dholland if (check_for_errors()) { 266 1.4 martin process_menu (MENU_sanity, &rv); 267 1.4 martin if (rv < 0) 268 1.10 martin return 0; 269 1.4 martin else if (rv) 270 1.1 dholland break; 271 1.1 dholland edit_diskmap(); 272 1.1 dholland } else 273 1.1 dholland break; 274 1.1 dholland } 275 1.1 dholland 276 1.9 martin /* Start with empty fake disklabel partitions */ 277 1.9 martin pm->parts->pscheme->delete_all_partitions(pm->parts); 278 1.1 dholland 279 1.1 dholland /* 280 1.1 dholland * Now, scan through the Disk Partition Map and transfer the 281 1.1 dholland * information into the incore disklabel. 282 1.1 dholland */ 283 1.1 dholland for (i=0;i<map.usable_cnt;i++) { 284 1.1 dholland j = map.mblk[i]; 285 1.1 dholland bzb = (EBZB *)&map.blk[j].pmBootArgs[0]; 286 1.1 dholland if (bzb->flags.part) { 287 1.9 martin mountpoint = NULL; 288 1.9 martin fs_type = FS_UNUSED; 289 1.1 dholland switch (whichType(&map.blk[j])) { 290 1.1 dholland case HFS_PART: 291 1.9 martin fs_type = FS_HFS; 292 1.9 martin mountpoint = (const char*)bzb->mount_point; 293 1.1 dholland break; 294 1.1 dholland case ROOT_PART: 295 1.1 dholland case UFS_PART: 296 1.9 martin fs_type = FS_BSDFFS; 297 1.9 martin mountpoint = (const char*)bzb->mount_point; 298 1.1 dholland break; 299 1.1 dholland case SWAP_PART: 300 1.9 martin fs_type = FS_SWAP; 301 1.1 dholland break; 302 1.1 dholland case SCRATCH_PART: 303 1.9 martin fs_type = FS_OTHER; 304 1.9 martin mountpoint = (const char*)bzb->mount_point; 305 1.9 martin break; 306 1.1 dholland default: 307 1.9 martin continue; 308 1.1 dholland } 309 1.9 martin if (fs_type != FS_UNUSED) { 310 1.9 martin memset(&info, 0, sizeof info); 311 1.9 martin info.start = map.blk[j].pmPyPartStart; 312 1.9 martin info.size = map.blk[j].pmPartBlkCnt; 313 1.9 martin info.fs_type = fs_type; 314 1.9 martin info.last_mounted = mountpoint; 315 1.9 martin info.nat_type = pm->parts->pscheme->get_fs_part_type( 316 1.9 martin PT_root, fs_type, 0); 317 1.9 martin pid = pm->parts->pscheme->add_outer_partition(pm->parts, 318 1.9 martin &info, NULL); 319 1.9 martin if (pid == NO_PART) 320 1.10 martin return 0; 321 1.1 dholland } 322 1.1 dholland } 323 1.1 dholland } 324 1.1 dholland 325 1.1 dholland /* Disk name - don't bother asking, just use the physical name*/ 326 1.9 martin pm->parts->pscheme->set_disk_pack_name(pm->parts, pm->diskdev); 327 1.1 dholland 328 1.9 martin /* Write the converted partitions */ 329 1.9 martin if (!pm->parts->pscheme->write_to_disk(pm->parts)) 330 1.10 martin return 0; 331 1.9 martin 332 1.9 martin /* now convert to install info */ 333 1.9 martin if (!install_desc_from_parts(install, pm->parts)) 334 1.10 martin return 0; 335 1.9 martin 336 1.9 martin /* set newfs flag for all FFS partitions */ 337 1.9 martin for (ndx = 0; ndx < install->num; ndx++) { 338 1.9 martin if (install->infos[ndx].fs_type == FS_BSDFFS && 339 1.9 martin install->infos[ndx].size > 0 && 340 1.9 martin (install->infos[ndx].instflags & PUIINST_MOUNT)) 341 1.9 martin install->infos[ndx].instflags |= PUIINST_NEWFS; 342 1.1 dholland } 343 1.1 dholland 344 1.10 martin return 1; 345 1.1 dholland } 346 1.1 dholland 347 1.1 dholland /* 348 1.1 dholland * any additional partition validation 349 1.1 dholland */ 350 1.6 martin bool 351 1.6 martin md_check_partitions(struct install_partition_desc *install) 352 1.1 dholland { 353 1.6 martin return true; 354 1.1 dholland } 355 1.1 dholland 356 1.1 dholland /* 357 1.1 dholland * hook called before writing new disklabel. 358 1.1 dholland */ 359 1.6 martin bool 360 1.6 martin md_pre_disklabel(struct install_partition_desc *install, 361 1.6 martin struct disk_partitions *parts) 362 1.1 dholland { 363 1.1 dholland int fd; 364 1.1 dholland char dev_name[100]; 365 1.1 dholland struct disklabel lp; 366 1.1 dholland Block0 new_block0 = {APPLE_DRVR_MAP_MAGIC, 512, 367 1.1 dholland 0, 0, 0, 0, 0, 0, 0, 0, {0}}; 368 1.1 dholland 369 1.1 dholland /* 370 1.1 dholland * Danger Will Robinson! We're about to turn that nice MacOS disk 371 1.1 dholland * into an expensive doorstop... 372 1.1 dholland */ 373 1.1 dholland printf ("%s", msg_string (MSG_dodiskmap)); 374 1.1 dholland 375 1.2 martin snprintf (dev_name, sizeof(dev_name), "/dev/r%sc", pm->diskdev); 376 1.1 dholland /* 377 1.1 dholland * Open the disk as a raw device 378 1.1 dholland */ 379 1.1 dholland if ((fd = open(dev_name, O_WRONLY, 0)) < 0) { 380 1.1 dholland endwin(); 381 1.1 dholland fprintf(stderr, "Can't open %s to rewrite the Disk Map\n", dev_name); 382 1.1 dholland exit (1); 383 1.1 dholland } 384 1.1 dholland /* 385 1.1 dholland * First check the pmSigPad field of the first block in the incore 386 1.1 dholland * Partition Map. It should be zero, but if it's 0xa5a5 that means 387 1.1 dholland * we need to write out Block0 too. 388 1.1 dholland */ 389 1.1 dholland if (map.blk[0].pmSigPad == 0xa5a5) { 390 1.1 dholland if (lseek (fd, (off_t)0 * blk_size, SEEK_SET) < 0) { 391 1.1 dholland endwin(); 392 1.1 dholland fprintf (stderr, "Can't position to write Block0\n"); 393 1.1 dholland close (fd); 394 1.1 dholland exit (1); 395 1.1 dholland } 396 1.2 martin new_block0.sbBlkCount = pm->dlsize; /* Set disk size */ 397 1.1 dholland if (write (fd, &new_block0, blk_size) != blk_size) { 398 1.1 dholland endwin(); 399 1.1 dholland fprintf (stderr, "I/O error writing Block0\n"); 400 1.1 dholland close (fd); 401 1.1 dholland exit (1); 402 1.1 dholland } 403 1.1 dholland map.blk[0].pmSigPad = 0; 404 1.1 dholland } 405 1.1 dholland if (lseek (fd, (off_t)1 * blk_size, SEEK_SET) < 0) { 406 1.1 dholland endwin(); 407 1.1 dholland fprintf (stderr, "Can't position disk to rewrite Disk Map\n"); 408 1.1 dholland close (fd); 409 1.1 dholland exit (1); 410 1.1 dholland } 411 1.1 dholland if (write (fd, map.blk, map.size * blk_size) != (map.size * blk_size)) { 412 1.1 dholland endwin(); 413 1.1 dholland fprintf(stderr, "I/O error writing Disk Map\n"); 414 1.1 dholland close (fd); 415 1.1 dholland exit (1); 416 1.1 dholland } 417 1.1 dholland fsync(fd); 418 1.1 dholland /* 419 1.1 dholland * Well, if we get here the dirty deed has been done. 420 1.1 dholland * 421 1.1 dholland * Now we need to force the incore disk table to get updated. This 422 1.1 dholland * should be done by disklabel -- which is normally called right after 423 1.1 dholland * we return -- but may be commented out for the mac68k port. We'll 424 1.1 dholland * instead update the incore table by forcing a dummy write here. This 425 1.2 martin * relies on a change in the mac68k-specific write_disklabel() routine. 426 1.1 dholland * If that change doesn't exist nothing bad happens here. If disklabel 427 1.1 dholland * properly updates the ondisk and incore labels everything still 428 1.1 dholland * works. Only if we fail here and if disklabel fails are we in 429 1.1 dholland * in a state where we've updated the disk but not the incore and 430 1.1 dholland * a reboot is necessary. 431 1.1 dholland * 432 1.1 dholland * First, we grab a copy of the incore label as it existed before 433 1.1 dholland * we did anything to it. Then we invoke the "write label" ioctl to 434 1.1 dholland * rewrite it to disk. As a result, the ondisk partition map is 435 1.1 dholland * re-read and the incore label is reconstructed from it. If 436 1.1 dholland * disklabel() is then called to update again, either that fails 437 1.1 dholland * because the mac68k port doesn't support native disklabels, or it 438 1.1 dholland * succeeds and writes out a new ondisk copy. 439 1.1 dholland */ 440 1.1 dholland ioctl(fd, DIOCGDINFO, &lp); /* Get the current disk label */ 441 1.1 dholland ioctl(fd, DIOCWDINFO, &lp); /* Write it out again */ 442 1.1 dholland 443 1.1 dholland close (fd); 444 1.6 martin return true; 445 1.1 dholland } 446 1.1 dholland 447 1.1 dholland /* 448 1.1 dholland * hook called after writing disklabel to new target disk. 449 1.1 dholland */ 450 1.6 martin bool 451 1.6 martin md_post_disklabel(struct install_partition_desc *install, 452 1.6 martin struct disk_partitions *parts) 453 1.1 dholland { 454 1.6 martin #if 0 // XXX 455 1.1 dholland struct disklabel updated_label; 456 1.1 dholland int fd, i, no_match; 457 1.1 dholland char dev_name[100], buf[80]; 458 1.1 dholland const char *fst[] = {"free", "swap", " v6 ", " v7 ", "sysv", "v71k", 459 1.1 dholland " v8 ", "ffs ", "dos ", "lfs ", "othr", "hpfs", 460 1.1 dholland "9660", "boot", "ados", "hfs ", "fcor", "ex2f", 461 1.1 dholland "ntfs", "raid", "ccd "}; 462 1.1 dholland 463 1.2 martin snprintf(dev_name, sizeof(dev_name), "/dev/r%sc", pm->diskdev); 464 1.1 dholland /* 465 1.1 dholland * Open the disk as a raw device 466 1.1 dholland */ 467 1.1 dholland if ((fd = open(dev_name, O_RDONLY, 0)) < 0) 468 1.6 martin return false; 469 1.1 dholland /* 470 1.1 dholland * Get the "new" label to see if we were successful. If we aren't 471 1.1 dholland * we'll return an error to keep from destroying the user's disk. 472 1.1 dholland */ 473 1.1 dholland ioctl(fd, DIOCGDINFO, &updated_label); 474 1.1 dholland close(fd); 475 1.1 dholland /* 476 1.1 dholland * Make sure the in-core label matches the on-disk one 477 1.1 dholland */ 478 1.1 dholland no_match = 0; 479 1.1 dholland for (i=0;i<MAXPARTITIONS;i++) { 480 1.1 dholland if (i > updated_label.d_npartitions) 481 1.1 dholland break; 482 1.2 martin if (pm->bsdlabel[i].pi_size != updated_label.d_partitions[i].p_size) 483 1.1 dholland no_match = 1; 484 1.2 martin if (pm->bsdlabel[i].pi_size) { 485 1.2 martin if (pm->bsdlabel[i].pi_offset != updated_label.d_partitions[i].p_offset) 486 1.1 dholland no_match = 1; 487 1.2 martin if (pm->bsdlabel[i].pi_fstype != updated_label.d_partitions[i].p_fstype) 488 1.1 dholland no_match = 1; 489 1.1 dholland } 490 1.1 dholland if (no_match) 491 1.1 dholland break; 492 1.1 dholland } 493 1.1 dholland /* 494 1.1 dholland * If the labels don't match, tell the user why 495 1.1 dholland */ 496 1.1 dholland if (no_match) { 497 1.1 dholland msg_clear(); 498 1.1 dholland msg_display(MSG_label_error); 499 1.7 christos msg_fmt_table_add(MSG_dump_line, "%s", 500 1.1 dholland " in-core: offset size type on-disk: offset size type"); 501 1.1 dholland for (i=0;i<MAXPARTITIONS;i++) { 502 1.7 christos snprintf(buf, sizeof(buf), 503 1.7 christos " %c:%13.8x%10.8x%5s%16.8x%10.8x%5s", i+'a', 504 1.2 martin pm->bsdlabel[i].pi_offset, pm->bsdlabel[i].pi_size, 505 1.2 martin fst[pm->bsdlabel[i].pi_fstype], 506 1.1 dholland updated_label.d_partitions[i].p_offset, 507 1.1 dholland updated_label.d_partitions[i].p_size, 508 1.1 dholland fst[updated_label.d_partitions[i].p_fstype]); 509 1.7 christos msg_fmt_table_add(MSG_dump_line, "%s", buf); 510 1.1 dholland } 511 1.1 dholland process_menu(MENU_ok2, NULL); 512 1.1 dholland } 513 1.6 martin return no_match == 0; 514 1.6 martin #else 515 1.6 martin return true; 516 1.6 martin #endif 517 1.1 dholland } 518 1.1 dholland 519 1.1 dholland /* 520 1.1 dholland * hook called after upgrade() or install() has finished setting 521 1.1 dholland * up the target disk but immediately before the user is given the 522 1.1 dholland * ``disks are now set up'' message. 523 1.1 dholland */ 524 1.1 dholland int 525 1.6 martin md_post_newfs(struct install_partition_desc *install) 526 1.1 dholland { 527 1.1 dholland return 0; 528 1.1 dholland } 529 1.1 dholland 530 1.1 dholland int 531 1.11 martin md_post_extract(struct install_partition_desc *install, bool upgrade) 532 1.1 dholland { 533 1.1 dholland return 0; 534 1.1 dholland } 535 1.1 dholland 536 1.1 dholland void 537 1.6 martin md_cleanup_install(struct install_partition_desc *install) 538 1.1 dholland { 539 1.1 dholland #ifndef DEBUG 540 1.1 dholland enable_rc_conf(); 541 1.1 dholland #endif 542 1.1 dholland } 543 1.1 dholland 544 1.1 dholland int 545 1.6 martin md_pre_update(struct install_partition_desc *install) 546 1.1 dholland { 547 1.1 dholland return 1; 548 1.1 dholland } 549 1.1 dholland 550 1.1 dholland /* Upgrade support */ 551 1.1 dholland int 552 1.6 martin md_update(struct install_partition_desc *install) 553 1.1 dholland { 554 1.6 martin md_post_newfs(install); 555 1.1 dholland return 1; 556 1.1 dholland } 557 1.1 dholland 558 1.1 dholland /* 559 1.1 dholland * Compare lexigraphically two strings 560 1.1 dholland */ 561 1.1 dholland static int 562 1.1 dholland stricmp(s1, s2) 563 1.1 dholland const char *s1; 564 1.1 dholland const char *s2; 565 1.1 dholland { 566 1.1 dholland char c1, c2; 567 1.1 dholland 568 1.1 dholland while (1) { 569 1.1 dholland c1 = tolower((unsigned char)*s1++); 570 1.1 dholland c2 = tolower((unsigned char)*s2++); 571 1.1 dholland if (c1 < c2) return -1; 572 1.1 dholland if (c1 > c2) return 1; 573 1.1 dholland if (c1 == 0) return 0; 574 1.1 dholland } 575 1.1 dholland } 576 1.1 dholland 577 1.1 dholland static void 578 1.1 dholland setpartition(part, in_use, slot) 579 1.1 dholland struct apple_part_map_entry *part; 580 1.1 dholland char in_use[]; 581 1.1 dholland int slot; 582 1.1 dholland { 583 1.1 dholland EBZB *bzb; 584 1.1 dholland 585 1.1 dholland bzb = (EBZB *)&part->pmBootArgs[0]; 586 1.1 dholland in_use[slot] = 1; 587 1.1 dholland bzb->flags.used = 1; 588 1.1 dholland bzb->flags.part = 'a' + slot; 589 1.1 dholland } 590 1.1 dholland 591 1.1 dholland /* 592 1.1 dholland * Find an entry in a use array that is unused and return it or 593 1.1 dholland * -1 if no entry is available 594 1.1 dholland */ 595 1.1 dholland static int 596 1.1 dholland getFreeLabelEntry(slots) 597 1.1 dholland char *slots; 598 1.1 dholland { 599 1.1 dholland int i; 600 1.1 dholland 601 1.1 dholland for ( i = 0; i < MAXPARTITIONS; i++) { 602 1.1 dholland if (i != RAW_PART && slots[i] == 0) 603 1.1 dholland return i; 604 1.1 dholland } 605 1.1 dholland return -1; 606 1.1 dholland } 607 1.1 dholland 608 1.1 dholland /* 609 1.1 dholland * Figure out what type type of the given partition is and return it. 610 1.1 dholland */ 611 1.1 dholland int 612 1.1 dholland whichType(part) 613 1.1 dholland struct apple_part_map_entry *part; 614 1.1 dholland { 615 1.1 dholland MAP_TYPE *map_entry = (MAP_TYPE *)&map_types; 616 1.1 dholland EBZB *bzb; 617 1.1 dholland char partyp[32]; 618 1.1 dholland int type, maxsiz, entry_type = MAP_OTHER; 619 1.1 dholland 620 1.1 dholland bzb = (EBZB *)&part->pmBootArgs[0]; 621 1.1 dholland if (part->pmSig != APPLE_PART_MAP_ENTRY_MAGIC) 622 1.1 dholland return 0; 623 1.1 dholland maxsiz = sizeof(part->pmPartType); 624 1.1 dholland if (maxsiz > (int)sizeof(partyp)) 625 1.1 dholland maxsiz = sizeof(partyp); 626 1.1 dholland strncpy(partyp, (char *)part->pmPartType, maxsiz); 627 1.1 dholland partyp[maxsiz-1] = '\0'; 628 1.1 dholland 629 1.1 dholland /* 630 1.1 dholland * Find out how to treat the partition type under NetBSD 631 1.1 dholland */ 632 1.1 dholland while (map_entry->type != MAP_EOL) { 633 1.1 dholland if (stricmp(map_entry->name, partyp) == 0) { 634 1.1 dholland entry_type = map_entry->type; 635 1.1 dholland break; 636 1.1 dholland } 637 1.1 dholland map_entry++; 638 1.1 dholland } 639 1.1 dholland 640 1.1 dholland /* 641 1.1 dholland * Now classify the use for NetBSD 642 1.1 dholland */ 643 1.1 dholland if (entry_type == MAP_RESERVED) 644 1.1 dholland type = 0; 645 1.1 dholland else if (entry_type == MAP_NETBSD) { 646 1.1 dholland if (bzb->magic != APPLE_BZB_MAGIC) 647 1.1 dholland type = 0; 648 1.1 dholland else if (bzb->type == APPLE_BZB_TYPEFS) { 649 1.1 dholland if (bzb->flags.root) 650 1.1 dholland type = ROOT_PART; 651 1.1 dholland else if (bzb->flags.usr) 652 1.1 dholland type = UFS_PART; 653 1.1 dholland else 654 1.1 dholland type = SCRATCH_PART; 655 1.1 dholland } else if (bzb->type == APPLE_BZB_TYPESWAP) 656 1.1 dholland type = SWAP_PART; 657 1.1 dholland else 658 1.1 dholland type = SCRATCH_PART; 659 1.1 dholland } else if (entry_type == MAP_MACOS) 660 1.1 dholland type = HFS_PART; 661 1.1 dholland else 662 1.1 dholland type = SCRATCH_PART; 663 1.1 dholland return type; 664 1.1 dholland } 665 1.1 dholland 666 1.1 dholland static char * 667 1.1 dholland getFstype(part, len_type, type) 668 1.1 dholland struct apple_part_map_entry *part; 669 1.1 dholland int len_type; 670 1.1 dholland char *type; 671 1.1 dholland { 672 1.1 dholland *type = '\0'; 673 1.1 dholland switch(whichType(part)) { 674 1.1 dholland case ROOT_PART: 675 1.1 dholland case UFS_PART: 676 1.1 dholland strncpy(type, "4.2BSD", len_type); 677 1.1 dholland break; 678 1.1 dholland case SWAP_PART: 679 1.1 dholland strncpy(type, "swap", len_type); 680 1.1 dholland break; 681 1.1 dholland case HFS_PART: 682 1.1 dholland strncpy(type, "HFS", len_type); 683 1.1 dholland break; 684 1.1 dholland case SCRATCH_PART: 685 1.1 dholland default: 686 1.1 dholland break; 687 1.1 dholland } 688 1.1 dholland return (type); 689 1.1 dholland } 690 1.1 dholland 691 1.1 dholland static char * 692 1.1 dholland getUse(part, len_use, use) 693 1.1 dholland struct apple_part_map_entry *part; 694 1.1 dholland int len_use; 695 1.1 dholland char *use; 696 1.1 dholland { 697 1.1 dholland EBZB *bzb; 698 1.1 dholland char partyp[32]; 699 1.1 dholland 700 1.1 dholland *use = '\0'; 701 1.1 dholland bzb = (EBZB *)&part->pmBootArgs[0]; 702 1.1 dholland switch(whichType(part)) { 703 1.1 dholland case ROOT_PART: 704 1.1 dholland if (bzb->flags.usr) 705 1.1 dholland strncpy(use, "Root&Usr", len_use); 706 1.1 dholland else 707 1.1 dholland strncpy(use, "Root", len_use); 708 1.1 dholland break; 709 1.1 dholland case UFS_PART: 710 1.1 dholland strncpy(use, "Usr", len_use); 711 1.1 dholland break; 712 1.1 dholland case SWAP_PART: 713 1.1 dholland break; 714 1.1 dholland case HFS_PART: 715 1.1 dholland strncpy(use, "MacOS", len_use); 716 1.1 dholland break; 717 1.1 dholland case SCRATCH_PART: 718 1.1 dholland strncpy(partyp, (char *)part->pmPartType, sizeof(partyp)); 719 1.1 dholland partyp[sizeof(partyp)-1] = '\0'; 720 1.1 dholland if (stricmp("Apple_Free", partyp) == 0) 721 1.1 dholland strncpy(use, "Free", len_use); 722 1.1 dholland else if (stricmp("Apple_Scratch", partyp) == 0) 723 1.1 dholland strncpy(use, "Scratch", len_use); 724 1.1 dholland else if (stricmp("Apple_MFS", partyp) == 0) 725 1.1 dholland strncpy(use, "MFS", len_use); 726 1.1 dholland else if (stricmp("Apple_PRODOS", partyp) == 0) 727 1.1 dholland strncpy(use, "PRODOS", len_use); 728 1.1 dholland else 729 1.1 dholland strncpy(use, "unknown", len_use); 730 1.1 dholland default: 731 1.1 dholland break; 732 1.1 dholland } 733 1.1 dholland return(use); 734 1.1 dholland } 735 1.1 dholland 736 1.1 dholland static char * 737 1.1 dholland getName(part, len_name, name) 738 1.1 dholland struct apple_part_map_entry *part; 739 1.1 dholland int len_name; 740 1.1 dholland char *name; 741 1.1 dholland { 742 1.1 dholland EBZB *bzb; 743 1.1 dholland int fd; 744 1.1 dholland off_t seek; 745 1.1 dholland char dev_name[100], macosblk[512]; 746 1.1 dholland 747 1.1 dholland *name = '\0'; 748 1.1 dholland bzb = (EBZB *)&part->pmBootArgs[0]; 749 1.1 dholland switch(whichType(part)) { 750 1.1 dholland case SCRATCH_PART: 751 1.1 dholland case ROOT_PART: 752 1.1 dholland case UFS_PART: 753 1.1 dholland strncpy(name, (char *)bzb->mount_point, len_name); 754 1.1 dholland break; 755 1.1 dholland case SWAP_PART: 756 1.1 dholland break; 757 1.1 dholland case HFS_PART: 758 1.1 dholland /* 759 1.1 dholland * OK, this is stupid but it's damn nice to know! 760 1.1 dholland */ 761 1.2 martin snprintf (dev_name, sizeof(dev_name), "/dev/r%sc", pm->diskdev); 762 1.1 dholland /* 763 1.1 dholland * Open the disk as a raw device 764 1.1 dholland */ 765 1.1 dholland if ((fd = open(dev_name, O_RDONLY, 0)) >= 0) { 766 1.1 dholland seek = (off_t)part->pmPyPartStart + (off_t)2; 767 1.1 dholland seek *= (off_t)blk_size; 768 1.1 dholland lseek(fd, seek, SEEK_SET); 769 1.1 dholland read(fd, &macosblk, sizeof(macosblk)); 770 1.1 dholland macosblk[37+32] = '\0'; 771 1.1 dholland strncpy(name, (char *)bzb->mount_point, len_name); 772 1.1 dholland strncat(name, " (", len_name-strlen(name)); 773 1.1 dholland strncat(name, &macosblk[37], len_name-strlen(name)); 774 1.1 dholland strncat(name, ")", len_name-strlen(name)); 775 1.1 dholland close(fd); 776 1.1 dholland } 777 1.1 dholland break; 778 1.1 dholland default: 779 1.1 dholland break; 780 1.1 dholland } 781 1.1 dholland return(name); 782 1.1 dholland } 783 1.1 dholland 784 1.1 dholland /* 785 1.12 andvar * Find the first occurrence of a Standard Type partition and 786 1.1 dholland * mark it for use along with the default mount slot. 787 1.1 dholland */ 788 1.1 dholland static int 789 1.1 dholland findStdType(num_parts, in_use, type, count, alt) 790 1.1 dholland int num_parts; 791 1.1 dholland char in_use[]; 792 1.1 dholland int type; 793 1.1 dholland int *count; 794 1.1 dholland int alt; 795 1.1 dholland { 796 1.1 dholland EBZB *bzb; 797 1.1 dholland int i; 798 1.1 dholland 799 1.1 dholland for (i = 0; i < num_parts; i++) { 800 1.1 dholland bzb = (EBZB *)&map.blk[i].pmBootArgs[0]; 801 1.1 dholland if (whichType(&map.blk[i]) != type || bzb->flags.used) 802 1.1 dholland continue; 803 1.1 dholland if (type == ROOT_PART) { 804 1.1 dholland if (alt >= 0 && alt != bzb->cluster) 805 1.1 dholland continue; 806 1.1 dholland setpartition(&map.blk[i], in_use, 0); 807 1.1 dholland strcpy ((char *)bzb->mount_point, "/"); 808 1.1 dholland *count += 1; 809 1.1 dholland } else if (type == UFS_PART) { 810 1.1 dholland if (alt >= 0 && alt != bzb->cluster) 811 1.1 dholland continue; 812 1.1 dholland setpartition(&map.blk[i], in_use, 6); 813 1.1 dholland if (bzb->mount_point[0] == '\0') 814 1.1 dholland strcpy ((char *)bzb->mount_point, "/usr"); 815 1.1 dholland *count += 1; 816 1.1 dholland } else if (type == SWAP_PART) { 817 1.1 dholland setpartition(&map.blk[i], in_use, 1); 818 1.1 dholland *count += 1; 819 1.1 dholland } 820 1.1 dholland return 0; 821 1.1 dholland } 822 1.1 dholland return -1; 823 1.1 dholland } 824 1.1 dholland 825 1.1 dholland /* 826 1.1 dholland * Reset the flags and reserved fields in the selected partition. 827 1.1 dholland * This functions isn't called to process any of the reserved partitions 828 1.1 dholland * where the boot code for MacOS is stored, so (hopefully) we won't 829 1.1 dholland * do more damage that we're trying to avoid. Eventually the NetBSD 830 1.1 dholland * Boot Code will need to go into a partition too, but that should go 831 1.1 dholland * into a reserved partition as well. I'd suggest using a partition 832 1.1 dholland * named something like "NetBSD_Boot" with a pmPartName of "Macintosh". 833 1.1 dholland * The Apple Start Manager (in ROM) will then recognize the partition 834 1.1 dholland * as the one containing the system bootstrip for the volume. 835 1.1 dholland */ 836 1.1 dholland void 837 1.1 dholland reset_part_flags(part) 838 1.1 dholland struct apple_part_map_entry *part; 839 1.1 dholland { 840 1.1 dholland EBZB *bzb; 841 1.1 dholland 842 1.1 dholland /* 843 1.1 dholland * Clear out the MacOS fields that might be used for booting just 844 1.1 dholland * in case we've clobbered the boot code. 845 1.1 dholland */ 846 1.1 dholland part->pmLgDataStart = 0; 847 1.1 dholland part->pmPartStatus = 0x77; /* make sure the partition shows up */ 848 1.1 dholland part->pmLgBootStart = 0; 849 1.1 dholland part->pmBootSize = 0; 850 1.1 dholland part->pmBootLoad = 0; 851 1.1 dholland part->pmBootLoad2 = 0; 852 1.1 dholland part->pmBootEntry = 0; 853 1.1 dholland part->pmBootEntry2 = 0; 854 1.1 dholland part->pmBootCksum = 0; 855 1.1 dholland 856 1.1 dholland /* 857 1.1 dholland * Clear out all the NetBSD fields too. We only clear out the ones 858 1.1 dholland * that should get reset during our processing. 859 1.1 dholland */ 860 1.1 dholland bzb = (EBZB *)&part->pmBootArgs[0]; 861 1.1 dholland bzb->magic = 0; 862 1.1 dholland bzb->cluster = 0; 863 1.1 dholland bzb->inode = 0; 864 1.1 dholland bzb->type = 0; 865 1.1 dholland bzb->flags.root = 0; 866 1.1 dholland bzb->flags.usr = 0; 867 1.1 dholland bzb->flags.crit = 0; 868 1.1 dholland bzb->flags.slice = 0; 869 1.1 dholland bzb->flags.used = 0; 870 1.1 dholland return; 871 1.1 dholland } 872 1.1 dholland 873 1.1 dholland /* 874 1.1 dholland * sortmerge: 875 1.1 dholland * 1) Moves all the Partition Map entries to the front of the Map. 876 1.1 dholland * This is required because some disk formatters leave holes. 877 1.1 dholland * 2) Sorts all entries by ascending start block number. 878 1.1 dholland * Needed so the NetBSD algorithm for finding partitions works 879 1.1 dholland * consistently from a user perspective. 880 1.1 dholland * 3) Collapse multiple adjected "free" entries into a single entry. 881 1.1 dholland * 4) Identify the NetBSD mount_points. 882 1.1 dholland */ 883 1.1 dholland void 884 1.1 dholland sortmerge(void) 885 1.1 dholland { 886 1.1 dholland struct apple_part_map_entry tmp_blk; 887 1.1 dholland char in_use[MAXPARTITIONS]; 888 1.1 dholland int i, j; 889 1.1 dholland EBZB *bzb; 890 1.1 dholland 891 1.1 dholland /* 892 1.1 dholland * Step 1, squeeze out the holes that some disk formatters leave in 893 1.1 dholland * the Map. Also convert any "old" Map entries to the new entry 894 1.14 andvar * type. Also clear out our used flag which is used to indicate 895 1.1 dholland * we've mapped the partition. 896 1.1 dholland */ 897 1.1 dholland map.in_use_cnt = 0; 898 1.1 dholland for (i=0;i<map.size-1;i++) { 899 1.1 dholland if (map.blk[i].pmSig == 0x5453) 900 1.1 dholland map.blk[i].pmSig = APPLE_PART_MAP_ENTRY_MAGIC; 901 1.1 dholland if (map.blk[i].pmSig != APPLE_PART_MAP_ENTRY_MAGIC) { 902 1.1 dholland for (j=i+1;j<map.size;j++) { 903 1.1 dholland if (map.blk[j].pmSig == 0x5453) 904 1.1 dholland map.blk[j].pmSig = APPLE_PART_MAP_ENTRY_MAGIC; 905 1.1 dholland if (map.blk[j].pmSig == APPLE_PART_MAP_ENTRY_MAGIC) { 906 1.1 dholland memcpy (&map.blk[i], &map.blk[j], sizeof(map.blk[i])); 907 1.1 dholland map.blk[j].pmSig = 0; 908 1.1 dholland break; 909 1.1 dholland } 910 1.1 dholland } 911 1.1 dholland } else { 912 1.1 dholland map.in_use_cnt += 1; 913 1.1 dholland bzb = (EBZB *)&map.blk[i].pmBootArgs[0]; 914 1.1 dholland bzb->flags.used = 0; 915 1.1 dholland bzb->flags.part = 0; 916 1.1 dholland } 917 1.1 dholland } 918 1.1 dholland 919 1.1 dholland /* 920 1.1 dholland * Step 2, sort by ascending starting block number. Since 921 1.1 dholland * we've already removed the holes we only need to 922 1.1 dholland * deal with the in_use count of blocks. 923 1.1 dholland */ 924 1.1 dholland for (i=0;i<map.in_use_cnt-1;i++) { 925 1.1 dholland for (j=i+1;j<map.in_use_cnt;j++) { 926 1.1 dholland if (map.blk[i].pmPyPartStart > map.blk[j].pmPyPartStart) { 927 1.1 dholland memcpy (&tmp_blk, &map.blk[i], sizeof(tmp_blk)); 928 1.1 dholland memcpy (&map.blk[i], &map.blk[j], sizeof(map.blk[i])); 929 1.1 dholland memcpy (&map.blk[j], &tmp_blk, sizeof(map.blk[j])); 930 1.1 dholland } 931 1.1 dholland } 932 1.1 dholland } 933 1.1 dholland 934 1.1 dholland /* 935 1.1 dholland * Step 3, merge adjacent free space 936 1.1 dholland */ 937 1.1 dholland for (i=0;i<map.in_use_cnt-1;i++) { 938 1.1 dholland if (stricmp("Apple_Free", (char *)map.blk[i].pmPartType) == 0 && 939 1.1 dholland stricmp("Apple_Free", (char *)map.blk[i+1].pmPartType) == 0) { 940 1.1 dholland map.blk[i].pmPartBlkCnt += map.blk[i+1].pmPartBlkCnt; 941 1.1 dholland map.blk[i].pmDataCnt += map.blk[i+1].pmDataCnt; 942 1.1 dholland map.blk[i+1].pmSig = 0; 943 1.1 dholland for (j=i+1;j<map.in_use_cnt-1;j++) { 944 1.1 dholland memcpy (&map.blk[j], &map.blk[j+1], sizeof(map.blk[j])); 945 1.1 dholland map.blk[j+1].pmSig = 0; 946 1.1 dholland } 947 1.1 dholland map.in_use_cnt -= 1; 948 1.1 dholland } 949 1.1 dholland } 950 1.1 dholland 951 1.1 dholland /* 952 1.1 dholland * Step 4, try to identify the mount points for the partitions 953 1.1 dholland * and adjust the pmMapBlkCnt in each Map entry. Set 954 1.1 dholland * up the display array for the non-reserved partitions, 955 1.1 dholland * and count the number of NetBSD usable partitions 956 1.1 dholland */ 957 1.1 dholland map.hfs_cnt = 0; 958 1.1 dholland map.root_cnt = 0; 959 1.1 dholland map.swap_cnt = 0; 960 1.1 dholland map.usr_cnt = 0; 961 1.1 dholland map.usable_cnt = 0; 962 1.1 dholland /* 963 1.1 dholland * Clear out record of partition slots already in use 964 1.1 dholland */ 965 1.1 dholland memset(&in_use, 0, sizeof(in_use)); 966 1.1 dholland for (i=0,j=0;i<map.in_use_cnt;i++) { 967 1.1 dholland map.blk[i].pmSig = APPLE_PART_MAP_ENTRY_MAGIC; 968 1.1 dholland map.blk[i].pmMapBlkCnt = map.in_use_cnt; 969 1.1 dholland /* 970 1.1 dholland * Since MAXPARTITIONS == 8 for mac68k, and we do not display 971 1.1 dholland * the c partition, we only need 7 partition slots on the screen. 972 1.1 dholland * If/when MAXPARTITIONS is changed, the "Edit Disk Partition Map" 973 1.1 dholland * needs to be a scrollable view of the partition table. 974 1.1 dholland */ 975 1.1 dholland if (whichType(&map.blk[i]) && (j < MAXPARTITIONS - 1)) { 976 1.1 dholland map.mblk[j++] = i; 977 1.1 dholland map.usable_cnt += 1; 978 1.1 dholland } 979 1.1 dholland } 980 1.1 dholland /* 981 1.1 dholland * Fill in standard partitions. Look for a Cluster "0" first and use 982 1.1 dholland * it, otherwise take any Cluster value. 983 1.1 dholland */ 984 1.1 dholland if (findStdType(map.in_use_cnt, in_use, ROOT_PART, &map.root_cnt, 0)) 985 1.1 dholland findStdType(map.in_use_cnt, in_use, ROOT_PART, &map.root_cnt, -1); 986 1.1 dholland if (findStdType(map.in_use_cnt, in_use, UFS_PART, &map.usr_cnt, 0)) 987 1.1 dholland findStdType(map.in_use_cnt, in_use, UFS_PART, &map.usr_cnt, -1); 988 1.1 dholland if (findStdType(map.in_use_cnt, in_use, SWAP_PART, &map.swap_cnt, 0)) 989 1.1 dholland findStdType(map.in_use_cnt, in_use, SWAP_PART, &map.swap_cnt, -1); 990 1.1 dholland 991 1.1 dholland #ifdef MD_DEBUG_SORT_MERGE 992 1.1 dholland md_debug_dump("After marking Standard Types"); 993 1.1 dholland #endif 994 1.1 dholland /* 995 1.1 dholland * Now fill in the remaining partitions counting them by type and 996 1.1 dholland * assigning them the slot the where the kernel should map them. 997 1.1 dholland * This will be where they are displayed in the Edit Map. 998 1.1 dholland */ 999 1.1 dholland for (i=0; i < map.in_use_cnt; i++) { 1000 1.1 dholland bzb = (EBZB *)&map.blk[i].pmBootArgs[0]; 1001 1.1 dholland if (bzb->flags.used == 0) { 1002 1.1 dholland if ((j = getFreeLabelEntry(in_use)) < 0) 1003 1.1 dholland break; 1004 1.1 dholland switch (whichType(&map.blk[i])) { 1005 1.1 dholland case ROOT_PART: 1006 1.1 dholland map.root_cnt += 1; 1007 1.1 dholland setpartition(&map.blk[i], in_use, j); 1008 1.1 dholland break; 1009 1.1 dholland case UFS_PART: 1010 1.1 dholland map.usr_cnt += 1; 1011 1.1 dholland setpartition(&map.blk[i], in_use, j); 1012 1.1 dholland break; 1013 1.1 dholland case SWAP_PART: 1014 1.1 dholland map.swap_cnt += 1; 1015 1.1 dholland setpartition(&map.blk[i], in_use, j); 1016 1.1 dholland break; 1017 1.1 dholland case HFS_PART: 1018 1.1 dholland map.hfs_cnt += 1; 1019 1.1 dholland setpartition(&map.blk[i], in_use, j); 1020 1.1 dholland break; 1021 1.1 dholland case SCRATCH_PART: 1022 1.1 dholland setpartition(&map.blk[i], in_use, j); 1023 1.1 dholland default: 1024 1.1 dholland break; 1025 1.1 dholland } 1026 1.1 dholland } 1027 1.1 dholland } 1028 1.1 dholland #ifdef MD_DEBUG_SORT_MERGE 1029 1.1 dholland md_debug_dump("After sort merge"); 1030 1.1 dholland #endif 1031 1.1 dholland return; 1032 1.1 dholland } 1033 1.1 dholland 1034 1.1 dholland void 1035 1.1 dholland disp_selected_part(sel) 1036 1.1 dholland int sel; 1037 1.1 dholland { 1038 1.1 dholland int i,j; 1039 1.1 dholland char fstyp[16], use[16], name[32]; 1040 1.1 dholland EBZB *bzb; 1041 1.1 dholland 1042 1.6 martin msg_table_add(MSG_mac68k_part_header); 1043 1.1 dholland for (i=0;i<map.usable_cnt;i++) { 1044 1.1 dholland if (i == sel) msg_standout(); 1045 1.1 dholland j = map.mblk[i]; 1046 1.1 dholland getFstype(&map.blk[j], sizeof(fstyp), fstyp); 1047 1.1 dholland getUse(&map.blk[j], sizeof(use), use); 1048 1.1 dholland getName(&map.blk[j], sizeof(name), name); 1049 1.1 dholland bzb = (EBZB *)&map.blk[j].pmBootArgs[0]; 1050 1.7 christos msg_fmt_table_add(MSG_part_row, "%s%c%d%d%s%s%s", 1051 1.7 christos pm->diskdev, 1052 1.1 dholland bzb->flags.part, map.blk[j].pmPyPartStart, 1053 1.1 dholland map.blk[j].pmPartBlkCnt, fstyp, use, name); 1054 1.1 dholland if (i == sel) msg_standend(); 1055 1.1 dholland } 1056 1.1 dholland return; 1057 1.1 dholland } 1058 1.1 dholland 1059 1.1 dholland /* 1060 1.1 dholland * check for any anomalies on the requested setup 1061 1.1 dholland */ 1062 1.1 dholland static int 1063 1.1 dholland check_for_errors() 1064 1.1 dholland { 1065 1.1 dholland int i, j; 1066 1.1 dholland int errs = 0; 1067 1.1 dholland 1068 1.1 dholland errs = (!map.root_cnt) || (map.root_cnt > 1) || (!map.swap_cnt) || 1069 1.1 dholland (map.swap_cnt > 1); 1070 1.1 dholland 1071 1.1 dholland for (i=0;i<map.usable_cnt;i++) { 1072 1.1 dholland j = map.mblk[i]; 1073 1.2 martin if (map.blk[j].pmPyPartStart > pm->dlsize) 1074 1.1 dholland errs++; 1075 1.2 martin if ((map.blk[j].pmPyPartStart + map.blk[j].pmPartBlkCnt) > pm->dlsize + 1) 1076 1.1 dholland errs++; 1077 1.1 dholland } 1078 1.1 dholland return(errs); 1079 1.1 dholland } 1080 1.1 dholland 1081 1.1 dholland /* 1082 1.1 dholland * check for and report anomalies on the requested setup 1083 1.1 dholland */ 1084 1.1 dholland void 1085 1.1 dholland report_errors() 1086 1.1 dholland { 1087 1.1 dholland int i, j; 1088 1.1 dholland int errs = 0; 1089 1.1 dholland EBZB *bzb; 1090 1.1 dholland 1091 1.1 dholland if (!map.root_cnt) { 1092 1.1 dholland msg_display_add(MSG_disksetup_no_root); 1093 1.1 dholland errs++; 1094 1.1 dholland } 1095 1.1 dholland if (map.root_cnt > 1) { 1096 1.1 dholland msg_display_add(MSG_disksetup_multiple_roots); 1097 1.1 dholland errs++; 1098 1.1 dholland } 1099 1.1 dholland if (!map.swap_cnt) { 1100 1.1 dholland msg_display_add(MSG_disksetup_no_swap); 1101 1.1 dholland errs++; 1102 1.1 dholland } 1103 1.1 dholland if (map.swap_cnt > 1) { 1104 1.1 dholland msg_display_add(MSG_disksetup_multiple_swaps); 1105 1.1 dholland errs++; 1106 1.1 dholland } 1107 1.1 dholland for (i=0;i<map.usable_cnt;i++) { 1108 1.1 dholland j = map.mblk[i]; 1109 1.2 martin if (map.blk[j].pmPyPartStart > pm->dlsize) { 1110 1.1 dholland bzb = (EBZB *)&map.blk[j].pmBootArgs[0]; 1111 1.7 christos msg_fmt_display_add(MSG_disksetup_part_beginning, "%s%c", 1112 1.2 martin pm->diskdev, bzb->flags.part); 1113 1.1 dholland errs++; 1114 1.1 dholland } 1115 1.2 martin if ((map.blk[j].pmPyPartStart + map.blk[j].pmPartBlkCnt) > pm->dlsize) { 1116 1.1 dholland bzb = (EBZB *)&map.blk[j].pmBootArgs[0]; 1117 1.7 christos msg_fmt_display_add(MSG_disksetup_part_size, "%s%c", 1118 1.2 martin pm->diskdev, bzb->flags.part); 1119 1.1 dholland errs++; 1120 1.1 dholland } 1121 1.1 dholland } 1122 1.1 dholland if (!errs) 1123 1.1 dholland msg_display_add(MSG_disksetup_noerrors); 1124 1.1 dholland return; 1125 1.1 dholland } 1126 1.1 dholland 1127 1.1 dholland static int 1128 1.1 dholland edit_diskmap(void) 1129 1.1 dholland { 1130 1.1 dholland int i; 1131 1.1 dholland 1132 1.1 dholland /* Ask full/part */ 1133 1.7 christos msg_fmt_display (MSG_mac68k_fullpart, "%s", pm->diskdev); 1134 1.1 dholland process_menu (MENU_fullpart, NULL); 1135 1.1 dholland 1136 1.1 dholland map.selected = 0; 1137 1.1 dholland sortmerge(); 1138 1.1 dholland 1139 1.1 dholland /* If blowing away the whole disk, let user know if there 1140 1.1 dholland * are any active disk partitions */ 1141 1.1 dholland if (usefull) { 1142 1.1 dholland if (map.usable_cnt > (map.root_cnt+map.swap_cnt+map.usr_cnt)) { 1143 1.6 martin msg_display (MSG_mac68k_ovrwrite); 1144 1.3 martin if (!ask_noyes(NULL)) { 1145 1.1 dholland endwin(); 1146 1.1 dholland return 0; 1147 1.1 dholland } 1148 1.1 dholland } 1149 1.1 dholland /* 1150 1.1 dholland * mark all non-reserved partitions as "free" 1151 1.1 dholland * then sort and merge the map into something sensible 1152 1.1 dholland */ 1153 1.1 dholland for (i=0;i<map.size;i++) 1154 1.1 dholland if (whichType(&map.blk[i])) 1155 1.1 dholland strcpy ((char *)map.blk[i].pmPartType, "Apple_Free"); 1156 1.1 dholland sortmerge(); 1157 1.1 dholland } 1158 1.1 dholland process_menu (MENU_editparttable, NULL); 1159 1.1 dholland return 1; 1160 1.1 dholland } 1161 1.1 dholland 1162 1.1 dholland #ifdef MD_DEBUG_SORT_MERGE 1163 1.1 dholland static int 1164 1.1 dholland md_debug_dump(title) 1165 1.1 dholland char *title; 1166 1.1 dholland { 1167 1.1 dholland char buf[96], type; 1168 1.1 dholland char fstyp[16], use[16], name[64]; 1169 1.4 martin int i, j, rv; 1170 1.1 dholland EBZB *bzb; 1171 1.1 dholland 1172 1.1 dholland msg_clear(); 1173 1.1 dholland sprintf(buf, "Apple Disk Partition Map: %s", title); 1174 1.7 christos msg_fmt_table_add(MSG_dump_line, "%s", buf); 1175 1.7 christos msg_fmt_table_add(MSG_dump_line, "%s", 1176 1.1 dholland "slot base fstype use name"); 1177 1.1 dholland for (i=0;i<map.in_use_cnt;i++) { 1178 1.1 dholland j = whichType(&map.blk[i]); 1179 1.1 dholland getFstype(&map.blk[i], sizeof(fstyp), fstyp); 1180 1.1 dholland getUse(&map.blk[i], sizeof(use), use); 1181 1.1 dholland getName(&map.blk[i], sizeof(name), name); 1182 1.1 dholland bzb = (EBZB *) &map.blk[i].pmBootArgs[0]; 1183 1.1 dholland type = bzb->flags.part; 1184 1.1 dholland if (type < 'a' || type > 'h') type = '?'; 1185 1.1 dholland if (j == 0) strcpy (name, "reserved for Apple"); 1186 1.1 dholland sprintf(buf, " %02d:%c %08x %8s %10s %s", i+1, type, 1187 1.1 dholland map.blk[i].pmPyPartStart, fstyp, use, name); 1188 1.7 christos msg_fmt_table_add(MSG_dump_line, "%s", buf); 1189 1.1 dholland } 1190 1.4 martin process_menu(MENU_okabort, &rv); 1191 1.1 dholland msg_clear(); 1192 1.4 martin return rv; 1193 1.1 dholland } 1194 1.1 dholland #endif /* MD_DEBUG_SORT_MERGE */ 1195 1.1 dholland 1196 1.1 dholland int 1197 1.8 martin md_pre_mount(struct install_partition_desc *install, size_t ndx) 1198 1.1 dholland { 1199 1.1 dholland return 0; 1200 1.1 dholland } 1201 1.6 martin 1202 1.6 martin bool 1203 1.6 martin md_parts_use_wholedisk(struct disk_partitions *parts) 1204 1.6 martin { 1205 1.6 martin return parts_use_wholedisk(parts, 0, NULL); 1206 1.6 martin } 1207 1.6 martin 1208 1.6 martin #ifdef HAVE_GPT 1209 1.6 martin bool 1210 1.6 martin md_gpt_post_write(struct disk_partitions *parts, part_id root_id, 1211 1.6 martin bool root_is_new, part_id efi_id, bool efi_is_new) 1212 1.6 martin { 1213 1.6 martin /* no GPT boot support, nothing needs to be done here */ 1214 1.6 martin return true; 1215 1.6 martin } 1216 1.6 martin #endif 1217 1.6 martin 1218