1 /* ofdisk.c - Open Firmware disk access. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2004,2006,2007,2008 Free Software Foundation, Inc.
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 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/misc.h>
21 #include <grub/disk.h>
23 #include <grub/ieee1275/ieee1275.h>
24 #include <grub/ieee1275/ofdisk.h>
26 struct ofdisk_hash_ent
29 struct ofdisk_hash_ent
*next
;
32 #define OFDISK_HASH_SZ 8
33 static struct ofdisk_hash_ent
*ofdisk_hash
[OFDISK_HASH_SZ
];
36 ofdisk_hash_fn (const char *devpath
)
41 return (hash
& (OFDISK_HASH_SZ
- 1));
44 static struct ofdisk_hash_ent
*
45 ofdisk_hash_find (const char *devpath
)
47 struct ofdisk_hash_ent
*p
= ofdisk_hash
[ofdisk_hash_fn(devpath
)];
51 if (!grub_strcmp (p
->devpath
, devpath
))
58 static struct ofdisk_hash_ent
*
59 ofdisk_hash_add (char *devpath
)
61 struct ofdisk_hash_ent
**head
= &ofdisk_hash
[ofdisk_hash_fn(devpath
)];
62 struct ofdisk_hash_ent
*p
= grub_malloc(sizeof (*p
));
74 grub_ofdisk_iterate (int (*hook
) (const char *name
))
76 auto int dev_iterate (struct grub_ieee1275_devalias
*alias
);
78 int dev_iterate (struct grub_ieee1275_devalias
*alias
)
82 grub_dprintf ("disk", "disk name = %s\n", alias
->name
);
84 if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY
))
86 grub_ieee1275_phandle_t dev
;
89 if (grub_ieee1275_finddevice (alias
->path
, &dev
))
91 grub_dprintf ("disk", "finddevice (%s) failed\n", alias
->path
);
95 if (grub_ieee1275_get_property (dev
, "iconname", tmp
,
98 grub_dprintf ("disk", "get iconname failed\n");
102 if (grub_strcmp (tmp
, "sdmmc"))
104 grub_dprintf ("disk", "device is not an SD card\n");
109 if (! grub_strcmp (alias
->type
, "block") &&
110 grub_strcmp (alias
->name
, "cdrom"))
111 ret
= hook (alias
->name
);
115 return grub_devalias_iterate (dev_iterate
);
119 compute_dev_path (const char *name
)
121 char *devpath
= grub_malloc (grub_strlen (name
) + 2);
127 /* Un-escape commas. */
129 while ((c
= *name
++) != '\0')
131 if (c
== '\\' && *name
== ',')
140 if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0
))
151 grub_ofdisk_open (const char *name
, grub_disk_t disk
)
153 grub_ieee1275_phandle_t dev
;
154 grub_ieee1275_ihandle_t dev_ihandle
= 0;
155 struct ofdisk_hash_ent
*op
;
157 /* XXX: This should be large enough for any possible case. */
161 devpath
= compute_dev_path (name
);
165 op
= ofdisk_hash_find (devpath
);
167 op
= ofdisk_hash_add (devpath
);
173 grub_dprintf ("disk", "Opening `%s'.\n", op
->devpath
);
175 grub_ieee1275_open (op
->devpath
, &dev_ihandle
);
178 grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "Can't open device");
182 grub_dprintf ("disk", "Opened `%s' as handle %p.\n", op
->devpath
,
183 (void *) (unsigned long) dev_ihandle
);
185 if (grub_ieee1275_finddevice (op
->devpath
, &dev
))
187 grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "Can't read device properties");
191 if (grub_ieee1275_get_property (dev
, "device_type", prop
, sizeof (prop
),
194 grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "Can't read the device type");
198 if (grub_strcmp (prop
, "block"))
200 grub_error (GRUB_ERR_BAD_DEVICE
, "Not a block device");
204 /* XXX: There is no property to read the number of blocks. There
205 should be a property `#blocks', but it is not there. Perhaps it
206 is possible to use seek for this. */
207 disk
->total_sectors
= 0xFFFFFFFFUL
;
209 disk
->id
= (unsigned long) op
;
211 /* XXX: Read this, somehow. */
212 disk
->has_partitions
= 1;
213 disk
->data
= (void *) (unsigned long) dev_ihandle
;
218 grub_ieee1275_close (dev_ihandle
);
223 grub_ofdisk_close (grub_disk_t disk
)
225 grub_dprintf ("disk", "Closing handle %p.\n",
226 (void *) disk
->data
);
227 grub_ieee1275_close ((grub_ieee1275_ihandle_t
) (unsigned long) disk
->data
);
231 grub_ofdisk_read (grub_disk_t disk
, grub_disk_addr_t sector
,
232 grub_size_t size
, char *buf
)
234 grub_ssize_t status
, actual
;
235 unsigned long long pos
;
237 grub_dprintf ("disk",
238 "Reading handle %p: sector 0x%llx, size 0x%lx, buf %p.\n",
239 (void *) disk
->data
, (long long) sector
, (long) size
, buf
);
241 pos
= sector
* 512UL;
243 grub_ieee1275_seek ((grub_ieee1275_ihandle_t
) (unsigned long) disk
->data
,
244 (int) (pos
>> 32), (int) pos
& 0xFFFFFFFFUL
, &status
);
246 return grub_error (GRUB_ERR_READ_ERROR
,
247 "Seek error, can't seek block %llu",
249 grub_ieee1275_read ((grub_ieee1275_ihandle_t
) (unsigned long) disk
->data
,
250 buf
, size
* 512UL, &actual
);
251 if (actual
!= actual
)
252 return grub_error (GRUB_ERR_READ_ERROR
, "Read error on block: %llu",
259 grub_ofdisk_write (grub_disk_t disk
__attribute ((unused
)),
260 grub_disk_addr_t sector
__attribute ((unused
)),
261 grub_size_t size
__attribute ((unused
)),
262 const char *buf
__attribute ((unused
)))
264 return GRUB_ERR_NOT_IMPLEMENTED_YET
;
267 static struct grub_disk_dev grub_ofdisk_dev
=
270 .id
= GRUB_DISK_DEVICE_OFDISK_ID
,
271 .iterate
= grub_ofdisk_iterate
,
272 .open
= grub_ofdisk_open
,
273 .close
= grub_ofdisk_close
,
274 .read
= grub_ofdisk_read
,
275 .write
= grub_ofdisk_write
,
280 grub_ofdisk_init (void)
282 grub_disk_dev_register (&grub_ofdisk_dev
);
286 grub_ofdisk_fini (void)
288 grub_disk_dev_unregister (&grub_ofdisk_dev
);