/* $NetBSD: md.c,v 1.12 2022/04/07 19:33:38 andvar Exp $ */ /* * Copyright 1997 Piermont Information Systems Inc. * All rights reserved. * * Based on code written by Philip A. Nelson for Piermont Information * Systems Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of Piermont Information Systems Inc. may not be used to endorse * or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /* md.c -- mac68k machine specific routines */ #include #include #include #include #include #include #include #include "defs.h" #include "md.h" #include "msg_defs.h" #include "menu_defs.h" static int stricmp(const char *c1, const char *c2); static void setpartition(struct apple_part_map_entry *, char *, int); static int getFreeLabelEntry(char *); static char *getFstype(struct apple_part_map_entry *, int, char *); static char *getUse(struct apple_part_map_entry *, int, char *); static char *getName(struct apple_part_map_entry *, int, char *); static int findStdType(int, char *, int, int *, int); static int check_for_errors(void); static int edit_diskmap(void); #ifdef MD_DEBUG_SORT_MERGE static int md_debug_dump(char *); #endif int blk_size; MAP_TYPE map_types[] = { {MAP_RESERVED, APPLE_PART_TYPE_DRIVER}, {MAP_RESERVED, APPLE_PART_TYPE_DRIVER43}, {MAP_RESERVED, APPLE_PART_TYPE_DRIVERATA}, {MAP_RESERVED, APPLE_PART_TYPE_FWB_COMPONENT}, {MAP_MACOS, APPLE_PART_TYPE_MAC}, {MAP_NETBSD, APPLE_PART_TYPE_NETBSD}, {MAP_RESERVED, APPLE_PART_TYPE_PARTMAP}, {MAP_OTHER, APPLE_PART_TYPE_SCRATCH}, {MAP_NETBSD, APPLE_PART_TYPE_UNIX}, {MAP_EOL, NULL} }; MAP map = {0, 0, 0, 0, 0, 0, 0, 0, {0}, NULL}; struct apple_part_map_entry new_map[] = { { APPLE_PART_MAP_ENTRY_MAGIC, 0xa5a5, 6, 1, NEW_MAP_SIZE & 0x7e, "Apple", "Apple_Partition_Map", 0, NEW_MAP_SIZE, 0x37, 0, 0, 0, 0, 0, 0, 0, {0}, {0}, {0}}, { APPLE_PART_MAP_ENTRY_MAGIC, 0, 6, 64, 32, "Macintosh", "Apple_Driver", 0, 0, 0x37, 0, 0, 0, 0, 0, 0, 0, {0}, {0}, {0}}, { APPLE_PART_MAP_ENTRY_MAGIC, 0, 6, 96, 64, "Macintosh", "Apple_Driver43", 0, 0, 0x37, 0, 0, 0, 0, 0, 0, 0, {0}, {0}, {0}}, { APPLE_PART_MAP_ENTRY_MAGIC, 0, 6, 160, 64, "Macintosh", "Apple_Driver_ATA", 0, 0, 0x37, 0, 0, 0, 0, 0, 0, 0, {0}, {0}, {0}}, { APPLE_PART_MAP_ENTRY_MAGIC, 0, 6, 224, 4096, "untitled", "Apple_HFS", 0, 0, 0x37, 0, 0, 0, 0, 0, 0, 0, {0}, {0}, {0}}, { APPLE_PART_MAP_ENTRY_MAGIC, 0, 6,4320, 0, "untitled", "Apple_Free", 0, 0, 0x37, 0, 0, 0, 0, 0, 0, 0, {0}, {0}, {0}} }; void md_init(void) { } void md_init_set_status(int flags) { struct utsname instsys; (void)flags; /* * Get the name of the Install Kernel we are running under and * enable the installation of the corresponding GENERIC kernel. * * Note: In md.h the two kernels are disabled. If they are * enabled there the logic here needs to be switched. */ uname(&instsys); if (strstr(instsys.version, "(INSTALLSBC)")) /* * Running the SBC Installation Kernel, so enable GENERICSBC */ set_kernel_set(SET_KERNEL_2); else /* * Running the GENERIC Installation Kernel, so enable GENERIC */ set_kernel_set(SET_KERNEL_1); } bool md_get_info(struct install_partition_desc *install) { struct disklabel disklabel; int fd, i; char dev_name[100]; struct apple_part_map_entry block; snprintf(dev_name, sizeof(dev_name), "/dev/r%s%c", pm->diskdev, 'a' + getrawpartition()); /* * Open the disk as a raw device */ fd = open(dev_name, O_RDONLY, 0); if (fd < 0) { endwin(); fprintf (stderr, "Can't open %s\n", dev_name); exit(1); } /* * Try to get the default disklabel info for the device */ if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) { endwin(); fprintf (stderr, "Can't read disklabel on %s\n", dev_name); close(fd); exit(1); } /* * Get the disk parameters from the disk driver. It should have * obained them by querying the disk itself. */ blk_size = disklabel.d_secsize; pm->dlcyl = disklabel.d_ncylinders; pm->dlhead = disklabel.d_ntracks; pm->dlsec = disklabel.d_nsectors; /* * Just in case, initialize the structures we'll need if we * need to completely initialize the disk. */ pm->dlsize = disklabel.d_secperunit; /* * XXX this code is broken: it accesses off the end of new_map[], * because NEW_MAP_SIZE is substantially larger than the number of * entries in new_map[]. Based on the description of struct * apple_part_map_entry in sys/bootblock.h, and the usage of it in * new_map[], NEW_MAP_SIZE is expected to be a block count, not an * entry count. As far I can tell the logic here is just wrong; it * needs someone with platform knowledge to sort it out. * * Note that nothing uses the data this writes into new_map[] so * disabling it should have no adverse consequences. * * - dholland 20160530 */ #if 0 /* XXX broken */ for (i=0;i 0) new_map[i].pmPyPartStart = new_map[i-1].pmPyPartStart + new_map[i-1].pmPartBlkCnt; new_map[i].pmDataCnt = new_map[i].pmPartBlkCnt; if (new_map[i].pmPartBlkCnt == 0) { new_map[i].pmPartBlkCnt = pm->dlsize; new_map[i].pmDataCnt = pm->dlsize; break; } pm->dlsize -= new_map[i].pmPartBlkCnt; } #endif /* 0 - broken */ pm->dlsize = disklabel.d_secperunit; #if 0 msg_fmt_display(MSG_dldebug, "%d%d%d%d%d", blk_size, pm->dlcyl, pm->dlhead, pm->dlsec, pm->dlsize); process_menu(MENU_ok, NULL); #endif map.size = 0; /* * Verify the disk has been initialized for MacOS use by checking * to see if the disk have a Boot Block */ if (lseek(fd, (off_t)0 * blk_size, SEEK_SET) < 0 || read(fd, &block, sizeof(block)) - sizeof(block) != 0 || block.pmSig != 0x4552) { process_menu(MENU_nodiskmap, NULL); } else { /* * Scan for the Partition Map entry that describes the Partition * Map itself. We need to know the number of blocks allocated * to it and the number currently in use. */ for (i=0;iparts->pscheme->delete_all_partitions(pm->parts); /* * Now, scan through the Disk Partition Map and transfer the * information into the incore disklabel. */ for (i=0;iflags.part) { mountpoint = NULL; fs_type = FS_UNUSED; switch (whichType(&map.blk[j])) { case HFS_PART: fs_type = FS_HFS; mountpoint = (const char*)bzb->mount_point; break; case ROOT_PART: case UFS_PART: fs_type = FS_BSDFFS; mountpoint = (const char*)bzb->mount_point; break; case SWAP_PART: fs_type = FS_SWAP; break; case SCRATCH_PART: fs_type = FS_OTHER; mountpoint = (const char*)bzb->mount_point; break; default: continue; } if (fs_type != FS_UNUSED) { memset(&info, 0, sizeof info); info.start = map.blk[j].pmPyPartStart; info.size = map.blk[j].pmPartBlkCnt; info.fs_type = fs_type; info.last_mounted = mountpoint; info.nat_type = pm->parts->pscheme->get_fs_part_type( PT_root, fs_type, 0); pid = pm->parts->pscheme->add_outer_partition(pm->parts, &info, NULL); if (pid == NO_PART) return 0; } } } /* Disk name - don't bother asking, just use the physical name*/ pm->parts->pscheme->set_disk_pack_name(pm->parts, pm->diskdev); /* Write the converted partitions */ if (!pm->parts->pscheme->write_to_disk(pm->parts)) return 0; /* now convert to install info */ if (!install_desc_from_parts(install, pm->parts)) return 0; /* set newfs flag for all FFS partitions */ for (ndx = 0; ndx < install->num; ndx++) { if (install->infos[ndx].fs_type == FS_BSDFFS && install->infos[ndx].size > 0 && (install->infos[ndx].instflags & PUIINST_MOUNT)) install->infos[ndx].instflags |= PUIINST_NEWFS; } return 1; } /* * any additional partition validation */ bool md_check_partitions(struct install_partition_desc *install) { return true; } /* * hook called before writing new disklabel. */ bool md_pre_disklabel(struct install_partition_desc *install, struct disk_partitions *parts) { int fd; char dev_name[100]; struct disklabel lp; Block0 new_block0 = {APPLE_DRVR_MAP_MAGIC, 512, 0, 0, 0, 0, 0, 0, 0, 0, {0}}; /* * Danger Will Robinson! We're about to turn that nice MacOS disk * into an expensive doorstop... */ printf ("%s", msg_string (MSG_dodiskmap)); snprintf (dev_name, sizeof(dev_name), "/dev/r%sc", pm->diskdev); /* * Open the disk as a raw device */ if ((fd = open(dev_name, O_WRONLY, 0)) < 0) { endwin(); fprintf(stderr, "Can't open %s to rewrite the Disk Map\n", dev_name); exit (1); } /* * First check the pmSigPad field of the first block in the incore * Partition Map. It should be zero, but if it's 0xa5a5 that means * we need to write out Block0 too. */ if (map.blk[0].pmSigPad == 0xa5a5) { if (lseek (fd, (off_t)0 * blk_size, SEEK_SET) < 0) { endwin(); fprintf (stderr, "Can't position to write Block0\n"); close (fd); exit (1); } new_block0.sbBlkCount = pm->dlsize; /* Set disk size */ if (write (fd, &new_block0, blk_size) != blk_size) { endwin(); fprintf (stderr, "I/O error writing Block0\n"); close (fd); exit (1); } map.blk[0].pmSigPad = 0; } if (lseek (fd, (off_t)1 * blk_size, SEEK_SET) < 0) { endwin(); fprintf (stderr, "Can't position disk to rewrite Disk Map\n"); close (fd); exit (1); } if (write (fd, map.blk, map.size * blk_size) != (map.size * blk_size)) { endwin(); fprintf(stderr, "I/O error writing Disk Map\n"); close (fd); exit (1); } fsync(fd); /* * Well, if we get here the dirty deed has been done. * * Now we need to force the incore disk table to get updated. This * should be done by disklabel -- which is normally called right after * we return -- but may be commented out for the mac68k port. We'll * instead update the incore table by forcing a dummy write here. This * relies on a change in the mac68k-specific write_disklabel() routine. * If that change doesn't exist nothing bad happens here. If disklabel * properly updates the ondisk and incore labels everything still * works. Only if we fail here and if disklabel fails are we in * in a state where we've updated the disk but not the incore and * a reboot is necessary. * * First, we grab a copy of the incore label as it existed before * we did anything to it. Then we invoke the "write label" ioctl to * rewrite it to disk. As a result, the ondisk partition map is * re-read and the incore label is reconstructed from it. If * disklabel() is then called to update again, either that fails * because the mac68k port doesn't support native disklabels, or it * succeeds and writes out a new ondisk copy. */ ioctl(fd, DIOCGDINFO, &lp); /* Get the current disk label */ ioctl(fd, DIOCWDINFO, &lp); /* Write it out again */ close (fd); return true; } /* * hook called after writing disklabel to new target disk. */ bool md_post_disklabel(struct install_partition_desc *install, struct disk_partitions *parts) { #if 0 // XXX struct disklabel updated_label; int fd, i, no_match; char dev_name[100], buf[80]; const char *fst[] = {"free", "swap", " v6 ", " v7 ", "sysv", "v71k", " v8 ", "ffs ", "dos ", "lfs ", "othr", "hpfs", "9660", "boot", "ados", "hfs ", "fcor", "ex2f", "ntfs", "raid", "ccd "}; snprintf(dev_name, sizeof(dev_name), "/dev/r%sc", pm->diskdev); /* * Open the disk as a raw device */ if ((fd = open(dev_name, O_RDONLY, 0)) < 0) return false; /* * Get the "new" label to see if we were successful. If we aren't * we'll return an error to keep from destroying the user's disk. */ ioctl(fd, DIOCGDINFO, &updated_label); close(fd); /* * Make sure the in-core label matches the on-disk one */ no_match = 0; for (i=0;i updated_label.d_npartitions) break; if (pm->bsdlabel[i].pi_size != updated_label.d_partitions[i].p_size) no_match = 1; if (pm->bsdlabel[i].pi_size) { if (pm->bsdlabel[i].pi_offset != updated_label.d_partitions[i].p_offset) no_match = 1; if (pm->bsdlabel[i].pi_fstype != updated_label.d_partitions[i].p_fstype) no_match = 1; } if (no_match) break; } /* * If the labels don't match, tell the user why */ if (no_match) { msg_clear(); msg_display(MSG_label_error); msg_fmt_table_add(MSG_dump_line, "%s", " in-core: offset size type on-disk: offset size type"); for (i=0;ibsdlabel[i].pi_offset, pm->bsdlabel[i].pi_size, fst[pm->bsdlabel[i].pi_fstype], updated_label.d_partitions[i].p_offset, updated_label.d_partitions[i].p_size, fst[updated_label.d_partitions[i].p_fstype]); msg_fmt_table_add(MSG_dump_line, "%s", buf); } process_menu(MENU_ok2, NULL); } return no_match == 0; #else return true; #endif } /* * hook called after upgrade() or install() has finished setting * up the target disk but immediately before the user is given the * ``disks are now set up'' message. */ int md_post_newfs(struct install_partition_desc *install) { return 0; } int md_post_extract(struct install_partition_desc *install, bool upgrade) { return 0; } void md_cleanup_install(struct install_partition_desc *install) { #ifndef DEBUG enable_rc_conf(); #endif } int md_pre_update(struct install_partition_desc *install) { return 1; } /* Upgrade support */ int md_update(struct install_partition_desc *install) { md_post_newfs(install); return 1; } /* * Compare lexigraphically two strings */ static int stricmp(s1, s2) const char *s1; const char *s2; { char c1, c2; while (1) { c1 = tolower((unsigned char)*s1++); c2 = tolower((unsigned char)*s2++); if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } static void setpartition(part, in_use, slot) struct apple_part_map_entry *part; char in_use[]; int slot; { EBZB *bzb; bzb = (EBZB *)&part->pmBootArgs[0]; in_use[slot] = 1; bzb->flags.used = 1; bzb->flags.part = 'a' + slot; } /* * Find an entry in a use array that is unused and return it or * -1 if no entry is available */ static int getFreeLabelEntry(slots) char *slots; { int i; for ( i = 0; i < MAXPARTITIONS; i++) { if (i != RAW_PART && slots[i] == 0) return i; } return -1; } /* * Figure out what type type of the given partition is and return it. */ int whichType(part) struct apple_part_map_entry *part; { MAP_TYPE *map_entry = (MAP_TYPE *)&map_types; EBZB *bzb; char partyp[32]; int type, maxsiz, entry_type = MAP_OTHER; bzb = (EBZB *)&part->pmBootArgs[0]; if (part->pmSig != APPLE_PART_MAP_ENTRY_MAGIC) return 0; maxsiz = sizeof(part->pmPartType); if (maxsiz > (int)sizeof(partyp)) maxsiz = sizeof(partyp); strncpy(partyp, (char *)part->pmPartType, maxsiz); partyp[maxsiz-1] = '\0'; /* * Find out how to treat the partition type under NetBSD */ while (map_entry->type != MAP_EOL) { if (stricmp(map_entry->name, partyp) == 0) { entry_type = map_entry->type; break; } map_entry++; } /* * Now classify the use for NetBSD */ if (entry_type == MAP_RESERVED) type = 0; else if (entry_type == MAP_NETBSD) { if (bzb->magic != APPLE_BZB_MAGIC) type = 0; else if (bzb->type == APPLE_BZB_TYPEFS) { if (bzb->flags.root) type = ROOT_PART; else if (bzb->flags.usr) type = UFS_PART; else type = SCRATCH_PART; } else if (bzb->type == APPLE_BZB_TYPESWAP) type = SWAP_PART; else type = SCRATCH_PART; } else if (entry_type == MAP_MACOS) type = HFS_PART; else type = SCRATCH_PART; return type; } static char * getFstype(part, len_type, type) struct apple_part_map_entry *part; int len_type; char *type; { *type = '\0'; switch(whichType(part)) { case ROOT_PART: case UFS_PART: strncpy(type, "4.2BSD", len_type); break; case SWAP_PART: strncpy(type, "swap", len_type); break; case HFS_PART: strncpy(type, "HFS", len_type); break; case SCRATCH_PART: default: break; } return (type); } static char * getUse(part, len_use, use) struct apple_part_map_entry *part; int len_use; char *use; { EBZB *bzb; char partyp[32]; *use = '\0'; bzb = (EBZB *)&part->pmBootArgs[0]; switch(whichType(part)) { case ROOT_PART: if (bzb->flags.usr) strncpy(use, "Root&Usr", len_use); else strncpy(use, "Root", len_use); break; case UFS_PART: strncpy(use, "Usr", len_use); break; case SWAP_PART: break; case HFS_PART: strncpy(use, "MacOS", len_use); break; case SCRATCH_PART: strncpy(partyp, (char *)part->pmPartType, sizeof(partyp)); partyp[sizeof(partyp)-1] = '\0'; if (stricmp("Apple_Free", partyp) == 0) strncpy(use, "Free", len_use); else if (stricmp("Apple_Scratch", partyp) == 0) strncpy(use, "Scratch", len_use); else if (stricmp("Apple_MFS", partyp) == 0) strncpy(use, "MFS", len_use); else if (stricmp("Apple_PRODOS", partyp) == 0) strncpy(use, "PRODOS", len_use); else strncpy(use, "unknown", len_use); default: break; } return(use); } static char * getName(part, len_name, name) struct apple_part_map_entry *part; int len_name; char *name; { EBZB *bzb; int fd; off_t seek; char dev_name[100], macosblk[512]; *name = '\0'; bzb = (EBZB *)&part->pmBootArgs[0]; switch(whichType(part)) { case SCRATCH_PART: case ROOT_PART: case UFS_PART: strncpy(name, (char *)bzb->mount_point, len_name); break; case SWAP_PART: break; case HFS_PART: /* * OK, this is stupid but it's damn nice to know! */ snprintf (dev_name, sizeof(dev_name), "/dev/r%sc", pm->diskdev); /* * Open the disk as a raw device */ if ((fd = open(dev_name, O_RDONLY, 0)) >= 0) { seek = (off_t)part->pmPyPartStart + (off_t)2; seek *= (off_t)blk_size; lseek(fd, seek, SEEK_SET); read(fd, &macosblk, sizeof(macosblk)); macosblk[37+32] = '\0'; strncpy(name, (char *)bzb->mount_point, len_name); strncat(name, " (", len_name-strlen(name)); strncat(name, &macosblk[37], len_name-strlen(name)); strncat(name, ")", len_name-strlen(name)); close(fd); } break; default: break; } return(name); } /* * Find the first occurrence of a Standard Type partition and * mark it for use along with the default mount slot. */ static int findStdType(num_parts, in_use, type, count, alt) int num_parts; char in_use[]; int type; int *count; int alt; { EBZB *bzb; int i; for (i = 0; i < num_parts; i++) { bzb = (EBZB *)&map.blk[i].pmBootArgs[0]; if (whichType(&map.blk[i]) != type || bzb->flags.used) continue; if (type == ROOT_PART) { if (alt >= 0 && alt != bzb->cluster) continue; setpartition(&map.blk[i], in_use, 0); strcpy ((char *)bzb->mount_point, "/"); *count += 1; } else if (type == UFS_PART) { if (alt >= 0 && alt != bzb->cluster) continue; setpartition(&map.blk[i], in_use, 6); if (bzb->mount_point[0] == '\0') strcpy ((char *)bzb->mount_point, "/usr"); *count += 1; } else if (type == SWAP_PART) { setpartition(&map.blk[i], in_use, 1); *count += 1; } return 0; } return -1; } /* * Reset the flags and reserved fields in the selected partition. * This functions isn't called to process any of the reserved partitions * where the boot code for MacOS is stored, so (hopefully) we won't * do more damage that we're trying to avoid. Eventually the NetBSD * Boot Code will need to go into a partition too, but that should go * into a reserved partition as well. I'd suggest using a partition * named something like "NetBSD_Boot" with a pmPartName of "Macintosh". * The Apple Start Manager (in ROM) will then recognize the partition * as the one containing the system bootstrip for the volume. */ void reset_part_flags(part) struct apple_part_map_entry *part; { EBZB *bzb; /* * Clear out the MacOS fields that might be used for booting just * in case we've clobbered the boot code. */ part->pmLgDataStart = 0; part->pmPartStatus = 0x77; /* make sure the partition shows up */ part->pmLgBootStart = 0; part->pmBootSize = 0; part->pmBootLoad = 0; part->pmBootLoad2 = 0; part->pmBootEntry = 0; part->pmBootEntry2 = 0; part->pmBootCksum = 0; /* * Clear out all the NetBSD fields too. We only clear out the ones * that should get reset during our processing. */ bzb = (EBZB *)&part->pmBootArgs[0]; bzb->magic = 0; bzb->cluster = 0; bzb->inode = 0; bzb->type = 0; bzb->flags.root = 0; bzb->flags.usr = 0; bzb->flags.crit = 0; bzb->flags.slice = 0; bzb->flags.used = 0; return; } /* * sortmerge: * 1) Moves all the Partition Map entries to the front of the Map. * This is required because some disk formatters leave holes. * 2) Sorts all entries by ascending start block number. * Needed so the NetBSD algorithm for finding partitions works * consistently from a user perspective. * 3) Collapse multiple adjected "free" entries into a single entry. * 4) Identify the NetBSD mount_points. */ void sortmerge(void) { struct apple_part_map_entry tmp_blk; char in_use[MAXPARTITIONS]; int i, j; EBZB *bzb; /* * Step 1, squeeze out the holes that some disk formatters leave in * the Map. Also convert any "old" Map entries to the new entry * type. Also clear out our used flag which is used to indicte * we've mapped the partition. */ map.in_use_cnt = 0; for (i=0;iflags.used = 0; bzb->flags.part = 0; } } /* * Step 2, sort by ascending starting block number. Since * we've already removed the holes we only need to * deal with the in_use count of blocks. */ for (i=0;i map.blk[j].pmPyPartStart) { memcpy (&tmp_blk, &map.blk[i], sizeof(tmp_blk)); memcpy (&map.blk[i], &map.blk[j], sizeof(map.blk[i])); memcpy (&map.blk[j], &tmp_blk, sizeof(map.blk[j])); } } } /* * Step 3, merge adjacent free space */ for (i=0;iflags.used == 0) { if ((j = getFreeLabelEntry(in_use)) < 0) break; switch (whichType(&map.blk[i])) { case ROOT_PART: map.root_cnt += 1; setpartition(&map.blk[i], in_use, j); break; case UFS_PART: map.usr_cnt += 1; setpartition(&map.blk[i], in_use, j); break; case SWAP_PART: map.swap_cnt += 1; setpartition(&map.blk[i], in_use, j); break; case HFS_PART: map.hfs_cnt += 1; setpartition(&map.blk[i], in_use, j); break; case SCRATCH_PART: setpartition(&map.blk[i], in_use, j); default: break; } } } #ifdef MD_DEBUG_SORT_MERGE md_debug_dump("After sort merge"); #endif return; } void disp_selected_part(sel) int sel; { int i,j; char fstyp[16], use[16], name[32]; EBZB *bzb; msg_table_add(MSG_mac68k_part_header); for (i=0;idiskdev, bzb->flags.part, map.blk[j].pmPyPartStart, map.blk[j].pmPartBlkCnt, fstyp, use, name); if (i == sel) msg_standend(); } return; } /* * check for any anomalies on the requested setup */ static int check_for_errors() { int i, j; int errs = 0; errs = (!map.root_cnt) || (map.root_cnt > 1) || (!map.swap_cnt) || (map.swap_cnt > 1); for (i=0;i pm->dlsize) errs++; if ((map.blk[j].pmPyPartStart + map.blk[j].pmPartBlkCnt) > pm->dlsize + 1) errs++; } return(errs); } /* * check for and report anomalies on the requested setup */ void report_errors() { int i, j; int errs = 0; EBZB *bzb; if (!map.root_cnt) { msg_display_add(MSG_disksetup_no_root); errs++; } if (map.root_cnt > 1) { msg_display_add(MSG_disksetup_multiple_roots); errs++; } if (!map.swap_cnt) { msg_display_add(MSG_disksetup_no_swap); errs++; } if (map.swap_cnt > 1) { msg_display_add(MSG_disksetup_multiple_swaps); errs++; } for (i=0;i pm->dlsize) { bzb = (EBZB *)&map.blk[j].pmBootArgs[0]; msg_fmt_display_add(MSG_disksetup_part_beginning, "%s%c", pm->diskdev, bzb->flags.part); errs++; } if ((map.blk[j].pmPyPartStart + map.blk[j].pmPartBlkCnt) > pm->dlsize) { bzb = (EBZB *)&map.blk[j].pmBootArgs[0]; msg_fmt_display_add(MSG_disksetup_part_size, "%s%c", pm->diskdev, bzb->flags.part); errs++; } } if (!errs) msg_display_add(MSG_disksetup_noerrors); return; } static int edit_diskmap(void) { int i; /* Ask full/part */ msg_fmt_display (MSG_mac68k_fullpart, "%s", pm->diskdev); process_menu (MENU_fullpart, NULL); map.selected = 0; sortmerge(); /* If blowing away the whole disk, let user know if there * are any active disk partitions */ if (usefull) { if (map.usable_cnt > (map.root_cnt+map.swap_cnt+map.usr_cnt)) { msg_display (MSG_mac68k_ovrwrite); if (!ask_noyes(NULL)) { endwin(); return 0; } } /* * mark all non-reserved partitions as "free" * then sort and merge the map into something sensible */ for (i=0;iflags.part; if (type < 'a' || type > 'h') type = '?'; if (j == 0) strcpy (name, "reserved for Apple"); sprintf(buf, " %02d:%c %08x %8s %10s %s", i+1, type, map.blk[i].pmPyPartStart, fstyp, use, name); msg_fmt_table_add(MSG_dump_line, "%s", buf); } process_menu(MENU_okabort, &rv); msg_clear(); return rv; } #endif /* MD_DEBUG_SORT_MERGE */ int md_pre_mount(struct install_partition_desc *install, size_t ndx) { return 0; } bool md_parts_use_wholedisk(struct disk_partitions *parts) { return parts_use_wholedisk(parts, 0, NULL); } #ifdef HAVE_GPT bool md_gpt_post_write(struct disk_partitions *parts, part_id root_id, bool root_is_new, part_id efi_id, bool efi_is_new) { /* no GPT boot support, nothing needs to be done here */ return true; } #endif