Blame view

fs/partitions/mac.c 3.1 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
  /*
   *  fs/partitions/mac.c
   *
   *  Code extracted from drivers/block/genhd.c
   *  Copyright (C) 1991-1998  Linus Torvalds
   *  Re-organised Feb 1998 Russell King
   */
  
  #include <linux/config.h>
  #include <linux/ctype.h>
  #include "check.h"
  #include "mac.h"
  
  #ifdef CONFIG_PPC_PMAC
  extern void note_bootable_part(dev_t dev, int part, int goodness);
  #endif
  
  /*
   * Code to understand MacOS partition tables.
   */
  
  static inline void mac_fix_string(char *stg, int len)
  {
  	int i;
  
  	for (i = len - 1; i >= 0 && stg[i] == ' '; i--)
  		stg[i] = 0;
  }
  
  int mac_partition(struct parsed_partitions *state, struct block_device *bdev)
  {
  	int slot = 1;
  	Sector sect;
  	unsigned char *data;
  	int blk, blocks_in_map;
  	unsigned secsize;
  #ifdef CONFIG_PPC_PMAC
  	int found_root = 0;
  	int found_root_goodness = 0;
  #endif
  	struct mac_partition *part;
  	struct mac_driver_desc *md;
  
  	/* Get 0th block and look at the first partition map entry. */
  	md = (struct mac_driver_desc *) read_dev_sector(bdev, 0, &sect);
  	if (!md)
  		return -1;
  	if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) {
  		put_dev_sector(sect);
  		return 0;
  	}
  	secsize = be16_to_cpu(md->block_size);
  	put_dev_sector(sect);
  	data = read_dev_sector(bdev, secsize/512, &sect);
  	if (!data)
  		return -1;
  	part = (struct mac_partition *) (data + secsize%512);
  	if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) {
  		put_dev_sector(sect);
  		return 0;		/* not a MacOS disk */
  	}
  	printk(" [mac]");
  	blocks_in_map = be32_to_cpu(part->map_count);
  	for (blk = 1; blk <= blocks_in_map; ++blk) {
  		int pos = blk * secsize;
  		put_dev_sector(sect);
  		data = read_dev_sector(bdev, pos/512, &sect);
  		if (!data)
  			return -1;
  		part = (struct mac_partition *) (data + pos%512);
  		if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
  			break;
  		put_partition(state, slot,
  			be32_to_cpu(part->start_block) * (secsize/512),
  			be32_to_cpu(part->block_count) * (secsize/512));
  
  #ifdef CONFIG_PPC_PMAC
  		/*
  		 * If this is the first bootable partition, tell the
  		 * setup code, in case it wants to make this the root.
  		 */
  		if (_machine == _MACH_Pmac) {
  			int goodness = 0;
  
  			mac_fix_string(part->processor, 16);
  			mac_fix_string(part->name, 32);
  			mac_fix_string(part->type, 32);					
  		    
  			if ((be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
  			    && strcasecmp(part->processor, "powerpc") == 0)
  				goodness++;
  
  			if (strcasecmp(part->type, "Apple_UNIX_SVR2") == 0
  			    || (strnicmp(part->type, "Linux", 5) == 0
  			        && strcasecmp(part->type, "Linux_swap") != 0)) {
  				int i, l;
  
  				goodness++;
  				l = strlen(part->name);
  				if (strcmp(part->name, "/") == 0)
  					goodness++;
  				for (i = 0; i <= l - 4; ++i) {
  					if (strnicmp(part->name + i, "root",
  						     4) == 0) {
  						goodness += 2;
  						break;
  					}
  				}
  				if (strnicmp(part->name, "swap", 4) == 0)
  					goodness--;
  			}
  
  			if (goodness > found_root_goodness) {
  				found_root = blk;
  				found_root_goodness = goodness;
  			}
  		}
  #endif /* CONFIG_PPC_PMAC */
  
  		++slot;
  	}
  #ifdef CONFIG_PPC_PMAC
  	if (found_root_goodness)
  		note_bootable_part(bdev->bd_dev, found_root, found_root_goodness);
  #endif
  
  	put_dev_sector(sect);
  	printk("
  ");
  	return 1;
  }