apple.c 4.99 KB
Newer Older
1 2 3
/* apple.c - Read macintosh partition tables.  */
/*
 *  GRUB  --  GRand Unified Bootloader
4
 *  Copyright (C) 2002,2004,2005,2006,2007,2008,2009  Free Software Foundation, Inc.
5
 *
6
 *  GRUB is free software: you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation, either version 3 of the License, or
9 10
 *  (at your option) any later version.
 *
11
 *  GRUB is distributed in the hope that it will be useful,
12 13 14 15 16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
17
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
18 19 20 21 22 23 24
 */

#include <grub/disk.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/partition.h>

25 26
GRUB_MOD_LICENSE ("GPLv3+");

27
#define GRUB_APPLE_HEADER_MAGIC	0x4552
28 29
#define GRUB_APPLE_PART_MAGIC	0x504D

30 31 32 33 34
struct grub_apple_header
{
  /* The magic number to identify the partition map, it should have
     the value `0x4552'.  */
  grub_uint16_t magic;
35
  grub_uint16_t blocksize;
36 37
};

38 39
struct grub_apple_part
{
40
  /* The magic number to identify this as a partition, it should have
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
     the value `0x504D'.  */
  grub_uint16_t magic;

  /* Reserved.  */
  grub_uint16_t reserved;

  /* The size of the partition map in blocks.  */
  grub_uint32_t partmap_size;

  /* The first physical block of the partition.  */
  grub_uint32_t first_phys_block;

  /* The amount of blocks.  */
  grub_uint32_t blockcnt;

  /* The partition name.  */
  char partname[32];

  /* The partition type.  */
  char parttype[32];

  /* The first datablock of the partition.  */
  grub_uint32_t datablocks_first;

  /* The amount datablocks.  */
  grub_uint32_t datablocks_count;

  /* The status of the partition. (???)  */
  grub_uint32_t status;

  /* The first block on which the bootcode can be found.  */
  grub_uint32_t bootcode_pos;

  /* The size of the bootcode in bytes.  */
  grub_uint32_t bootcode_size;

  /* The load address of the bootcode.  */
  grub_uint32_t bootcode_loadaddr;

  /* Reserved.  */
  grub_uint32_t reserved2;
82

83
  /* The entry point of the bootcode.  */
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
  grub_uint32_t bootcode_entrypoint;

  /* Reserved.  */
  grub_uint32_t reserved3;

  /* A checksum of the bootcode.  */
  grub_uint32_t bootcode_checksum;

  /* The processor type.  */
  char processor[16];

  /* Padding.  */
  grub_uint16_t pad[187];
};

static struct grub_partition_map grub_apple_partition_map;


static grub_err_t
apple_partition_map_iterate (grub_disk_t disk,
104 105
			     grub_partition_iterate_hook_t hook,
			     void *hook_data)
106 107
{
  struct grub_partition part;
108
  struct grub_apple_header aheader;
109
  struct grub_apple_part apart;
110 111
  int partno = 0, partnum = 0;
  unsigned pos;
112 113

  part.partmap = &grub_apple_partition_map;
114

115
  if (grub_disk_read (disk, 0, 0, sizeof (aheader), &aheader))
116 117 118 119 120
    return grub_errno;

  if (grub_be_to_cpu16 (aheader.magic) != GRUB_APPLE_HEADER_MAGIC)
    {
      grub_dprintf ("partition",
121
		    "bad magic (found 0x%x; wanted 0x%x)\n",
122 123 124 125 126
		    grub_be_to_cpu16 (aheader.magic),
		    GRUB_APPLE_HEADER_MAGIC);
      goto fail;
    }

127 128 129
  pos = grub_be_to_cpu16 (aheader.blocksize);

  do
130
    {
131 132
      part.offset = pos / GRUB_DISK_SECTOR_SIZE;
      part.index = pos % GRUB_DISK_SECTOR_SIZE;
133

134 135 136
      if (grub_disk_read (disk, part.offset, part.index,
			  sizeof (struct grub_apple_part),  &apart))
	return grub_errno;
137

138
      if (grub_be_to_cpu16 (apart.magic) != GRUB_APPLE_PART_MAGIC)
139 140
	{
	  grub_dprintf ("partition",
141
			"partition %d: bad magic (found 0x%x; wanted 0x%x)\n",
142 143
			partno, grub_be_to_cpu16 (apart.magic),
			GRUB_APPLE_PART_MAGIC);
144 145
	  break;
	}
146

147 148 149 150 151 152 153 154 155
      if (partnum == 0)
	partnum = grub_be_to_cpu32 (apart.partmap_size);

      part.start = ((grub_disk_addr_t) grub_be_to_cpu32 (apart.first_phys_block)
		    * grub_be_to_cpu16 (aheader.blocksize))
	/ GRUB_DISK_SECTOR_SIZE;
      part.len = ((grub_disk_addr_t) grub_be_to_cpu32 (apart.blockcnt)
		  * grub_be_to_cpu16 (aheader.blocksize))
	/ GRUB_DISK_SECTOR_SIZE;
156 157
      part.offset = pos;
      part.index = partno;
158
      part.number = partno;
159

160 161 162
      grub_dprintf ("partition",
		    "partition %d: name %s, type %s, start 0x%x, len 0x%x\n",
		    partno, apart.partname, apart.parttype,
163 164
		    grub_be_to_cpu32 (apart.first_phys_block),
		    grub_be_to_cpu32 (apart.blockcnt));
165

166
      if (hook (disk, &part, hook_data))
167 168
	return grub_errno;

169
      pos += grub_be_to_cpu16 (aheader.blocksize);
170 171
      partno++;
    }
172
  while (partno < partnum);
173

174
  if (partno != 0)
175
    return 0;
176

177 178
 fail:
  return grub_error (GRUB_ERR_BAD_PART_TABLE,
179
		     "Apple partition map not found");
180 181 182 183 184 185
}


/* Partition map type.  */
static struct grub_partition_map grub_apple_partition_map =
  {
186
    .name = "apple",
187 188 189
    .iterate = apple_partition_map_iterate,
  };

190
GRUB_MOD_INIT(part_apple)
191 192 193 194
{
  grub_partition_map_register (&grub_apple_partition_map);
}

195
GRUB_MOD_FINI(part_apple)
196 197 198
{
  grub_partition_map_unregister (&grub_apple_partition_map);
}
199