Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  fs/partitions/mac.c
0004  *
0005  *  Code extracted from drivers/block/genhd.c
0006  *  Copyright (C) 1991-1998  Linus Torvalds
0007  *  Re-organised Feb 1998 Russell King
0008  */
0009 
0010 #include <linux/ctype.h>
0011 #include "check.h"
0012 #include "mac.h"
0013 
0014 #ifdef CONFIG_PPC_PMAC
0015 #include <asm/machdep.h>
0016 extern void note_bootable_part(dev_t dev, int part, int goodness);
0017 #endif
0018 
0019 /*
0020  * Code to understand MacOS partition tables.
0021  */
0022 
0023 static inline void mac_fix_string(char *stg, int len)
0024 {
0025     int i;
0026 
0027     for (i = len - 1; i >= 0 && stg[i] == ' '; i--)
0028         stg[i] = 0;
0029 }
0030 
0031 int mac_partition(struct parsed_partitions *state)
0032 {
0033     Sector sect;
0034     unsigned char *data;
0035     int slot, blocks_in_map;
0036     unsigned secsize, datasize, partoffset;
0037 #ifdef CONFIG_PPC_PMAC
0038     int found_root = 0;
0039     int found_root_goodness = 0;
0040 #endif
0041     struct mac_partition *part;
0042     struct mac_driver_desc *md;
0043 
0044     /* Get 0th block and look at the first partition map entry. */
0045     md = read_part_sector(state, 0, &sect);
0046     if (!md)
0047         return -1;
0048     if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) {
0049         put_dev_sector(sect);
0050         return 0;
0051     }
0052     secsize = be16_to_cpu(md->block_size);
0053     put_dev_sector(sect);
0054     datasize = round_down(secsize, 512);
0055     data = read_part_sector(state, datasize / 512, &sect);
0056     if (!data)
0057         return -1;
0058     partoffset = secsize % 512;
0059     if (partoffset + sizeof(*part) > datasize)
0060         return -1;
0061     part = (struct mac_partition *) (data + partoffset);
0062     if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) {
0063         put_dev_sector(sect);
0064         return 0;       /* not a MacOS disk */
0065     }
0066     blocks_in_map = be32_to_cpu(part->map_count);
0067     if (blocks_in_map < 0 || blocks_in_map >= DISK_MAX_PARTS) {
0068         put_dev_sector(sect);
0069         return 0;
0070     }
0071 
0072     if (blocks_in_map >= state->limit)
0073         blocks_in_map = state->limit - 1;
0074 
0075     strlcat(state->pp_buf, " [mac]", PAGE_SIZE);
0076     for (slot = 1; slot <= blocks_in_map; ++slot) {
0077         int pos = slot * secsize;
0078         put_dev_sector(sect);
0079         data = read_part_sector(state, pos/512, &sect);
0080         if (!data)
0081             return -1;
0082         part = (struct mac_partition *) (data + pos%512);
0083         if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
0084             break;
0085         put_partition(state, slot,
0086             be32_to_cpu(part->start_block) * (secsize/512),
0087             be32_to_cpu(part->block_count) * (secsize/512));
0088 
0089         if (!strncasecmp(part->type, "Linux_RAID", 10))
0090             state->parts[slot].flags = ADDPART_FLAG_RAID;
0091 #ifdef CONFIG_PPC_PMAC
0092         /*
0093          * If this is the first bootable partition, tell the
0094          * setup code, in case it wants to make this the root.
0095          */
0096         if (machine_is(powermac)) {
0097             int goodness = 0;
0098 
0099             mac_fix_string(part->processor, 16);
0100             mac_fix_string(part->name, 32);
0101             mac_fix_string(part->type, 32);                 
0102             
0103             if ((be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
0104                 && strcasecmp(part->processor, "powerpc") == 0)
0105                 goodness++;
0106 
0107             if (strcasecmp(part->type, "Apple_UNIX_SVR2") == 0
0108                 || (strncasecmp(part->type, "Linux", 5) == 0
0109                     && strcasecmp(part->type, "Linux_swap") != 0)) {
0110                 int i, l;
0111 
0112                 goodness++;
0113                 l = strlen(part->name);
0114                 if (strcmp(part->name, "/") == 0)
0115                     goodness++;
0116                 for (i = 0; i <= l - 4; ++i) {
0117                     if (strncasecmp(part->name + i, "root",
0118                              4) == 0) {
0119                         goodness += 2;
0120                         break;
0121                     }
0122                 }
0123                 if (strncasecmp(part->name, "swap", 4) == 0)
0124                     goodness--;
0125             }
0126 
0127             if (goodness > found_root_goodness) {
0128                 found_root = slot;
0129                 found_root_goodness = goodness;
0130             }
0131         }
0132 #endif /* CONFIG_PPC_PMAC */
0133     }
0134 #ifdef CONFIG_PPC_PMAC
0135     if (found_root_goodness)
0136         note_bootable_part(state->disk->part0->bd_dev, found_root,
0137                    found_root_goodness);
0138 #endif
0139 
0140     put_dev_sector(sect);
0141     strlcat(state->pp_buf, "\n", PAGE_SIZE);
0142     return 1;
0143 }