162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * fs/partitions/mac.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Code extracted from drivers/block/genhd.c 662306a36Sopenharmony_ci * Copyright (C) 1991-1998 Linus Torvalds 762306a36Sopenharmony_ci * Re-organised Feb 1998 Russell King 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/ctype.h> 1162306a36Sopenharmony_ci#include "check.h" 1262306a36Sopenharmony_ci#include "mac.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#ifdef CONFIG_PPC_PMAC 1562306a36Sopenharmony_ci#include <asm/machdep.h> 1662306a36Sopenharmony_ciextern void note_bootable_part(dev_t dev, int part, int goodness); 1762306a36Sopenharmony_ci#endif 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* 2062306a36Sopenharmony_ci * Code to understand MacOS partition tables. 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic inline void mac_fix_string(char *stg, int len) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci int i; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci for (i = len - 1; i >= 0 && stg[i] == ' '; i--) 2862306a36Sopenharmony_ci stg[i] = 0; 2962306a36Sopenharmony_ci} 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ciint mac_partition(struct parsed_partitions *state) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci Sector sect; 3462306a36Sopenharmony_ci unsigned char *data; 3562306a36Sopenharmony_ci int slot, blocks_in_map; 3662306a36Sopenharmony_ci unsigned secsize, datasize, partoffset; 3762306a36Sopenharmony_ci#ifdef CONFIG_PPC_PMAC 3862306a36Sopenharmony_ci int found_root = 0; 3962306a36Sopenharmony_ci int found_root_goodness = 0; 4062306a36Sopenharmony_ci#endif 4162306a36Sopenharmony_ci struct mac_partition *part; 4262306a36Sopenharmony_ci struct mac_driver_desc *md; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci /* Get 0th block and look at the first partition map entry. */ 4562306a36Sopenharmony_ci md = read_part_sector(state, 0, §); 4662306a36Sopenharmony_ci if (!md) 4762306a36Sopenharmony_ci return -1; 4862306a36Sopenharmony_ci if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) { 4962306a36Sopenharmony_ci put_dev_sector(sect); 5062306a36Sopenharmony_ci return 0; 5162306a36Sopenharmony_ci } 5262306a36Sopenharmony_ci secsize = be16_to_cpu(md->block_size); 5362306a36Sopenharmony_ci put_dev_sector(sect); 5462306a36Sopenharmony_ci datasize = round_down(secsize, 512); 5562306a36Sopenharmony_ci data = read_part_sector(state, datasize / 512, §); 5662306a36Sopenharmony_ci if (!data) 5762306a36Sopenharmony_ci return -1; 5862306a36Sopenharmony_ci partoffset = secsize % 512; 5962306a36Sopenharmony_ci if (partoffset + sizeof(*part) > datasize) 6062306a36Sopenharmony_ci return -1; 6162306a36Sopenharmony_ci part = (struct mac_partition *) (data + partoffset); 6262306a36Sopenharmony_ci if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) { 6362306a36Sopenharmony_ci put_dev_sector(sect); 6462306a36Sopenharmony_ci return 0; /* not a MacOS disk */ 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci blocks_in_map = be32_to_cpu(part->map_count); 6762306a36Sopenharmony_ci if (blocks_in_map < 0 || blocks_in_map >= DISK_MAX_PARTS) { 6862306a36Sopenharmony_ci put_dev_sector(sect); 6962306a36Sopenharmony_ci return 0; 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci if (blocks_in_map >= state->limit) 7362306a36Sopenharmony_ci blocks_in_map = state->limit - 1; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci strlcat(state->pp_buf, " [mac]", PAGE_SIZE); 7662306a36Sopenharmony_ci for (slot = 1; slot <= blocks_in_map; ++slot) { 7762306a36Sopenharmony_ci int pos = slot * secsize; 7862306a36Sopenharmony_ci put_dev_sector(sect); 7962306a36Sopenharmony_ci data = read_part_sector(state, pos/512, §); 8062306a36Sopenharmony_ci if (!data) 8162306a36Sopenharmony_ci return -1; 8262306a36Sopenharmony_ci part = (struct mac_partition *) (data + pos%512); 8362306a36Sopenharmony_ci if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) 8462306a36Sopenharmony_ci break; 8562306a36Sopenharmony_ci put_partition(state, slot, 8662306a36Sopenharmony_ci be32_to_cpu(part->start_block) * (secsize/512), 8762306a36Sopenharmony_ci be32_to_cpu(part->block_count) * (secsize/512)); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci if (!strncasecmp(part->type, "Linux_RAID", 10)) 9062306a36Sopenharmony_ci state->parts[slot].flags = ADDPART_FLAG_RAID; 9162306a36Sopenharmony_ci#ifdef CONFIG_PPC_PMAC 9262306a36Sopenharmony_ci /* 9362306a36Sopenharmony_ci * If this is the first bootable partition, tell the 9462306a36Sopenharmony_ci * setup code, in case it wants to make this the root. 9562306a36Sopenharmony_ci */ 9662306a36Sopenharmony_ci if (machine_is(powermac)) { 9762306a36Sopenharmony_ci int goodness = 0; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci mac_fix_string(part->processor, 16); 10062306a36Sopenharmony_ci mac_fix_string(part->name, 32); 10162306a36Sopenharmony_ci mac_fix_string(part->type, 32); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci if ((be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE) 10462306a36Sopenharmony_ci && strcasecmp(part->processor, "powerpc") == 0) 10562306a36Sopenharmony_ci goodness++; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci if (strcasecmp(part->type, "Apple_UNIX_SVR2") == 0 10862306a36Sopenharmony_ci || (strncasecmp(part->type, "Linux", 5) == 0 10962306a36Sopenharmony_ci && strcasecmp(part->type, "Linux_swap") != 0)) { 11062306a36Sopenharmony_ci int i, l; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci goodness++; 11362306a36Sopenharmony_ci l = strlen(part->name); 11462306a36Sopenharmony_ci if (strcmp(part->name, "/") == 0) 11562306a36Sopenharmony_ci goodness++; 11662306a36Sopenharmony_ci for (i = 0; i <= l - 4; ++i) { 11762306a36Sopenharmony_ci if (strncasecmp(part->name + i, "root", 11862306a36Sopenharmony_ci 4) == 0) { 11962306a36Sopenharmony_ci goodness += 2; 12062306a36Sopenharmony_ci break; 12162306a36Sopenharmony_ci } 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci if (strncasecmp(part->name, "swap", 4) == 0) 12462306a36Sopenharmony_ci goodness--; 12562306a36Sopenharmony_ci } 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci if (goodness > found_root_goodness) { 12862306a36Sopenharmony_ci found_root = slot; 12962306a36Sopenharmony_ci found_root_goodness = goodness; 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci#endif /* CONFIG_PPC_PMAC */ 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci#ifdef CONFIG_PPC_PMAC 13562306a36Sopenharmony_ci if (found_root_goodness) 13662306a36Sopenharmony_ci note_bootable_part(state->disk->part0->bd_dev, found_root, 13762306a36Sopenharmony_ci found_root_goodness); 13862306a36Sopenharmony_ci#endif 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci put_dev_sector(sect); 14162306a36Sopenharmony_ci strlcat(state->pp_buf, "\n", PAGE_SIZE); 14262306a36Sopenharmony_ci return 1; 14362306a36Sopenharmony_ci} 144