]>
Commit | Line | Data |
---|---|---|
e56cdf21 | 1 | /* ofdisk.c - Open Firmware disk access. */ |
2 | /* | |
4b13b216 | 3 | * GRUB -- GRand Unified Bootloader |
e56cdf21 | 4 | * Copyright (C) 2004 Free Software Foundation, Inc. |
5 | * | |
6 | * This program 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 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program 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. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program; if not, write to the Free Software | |
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
19 | */ | |
20 | ||
4b13b216 | 21 | #include <grub/misc.h> |
22 | #include <grub/disk.h> | |
23 | #include <grub/mm.h> | |
24 | #include <grub/machine/ieee1275.h> | |
924b6140 | 25 | #include <grub/machine/init.h> |
e56cdf21 | 26 | |
27 | static int | |
4b13b216 | 28 | grub_ofdisk_iterate (int (*hook) (const char *name)) |
e56cdf21 | 29 | { |
924b6140 | 30 | auto int dev_iterate (struct grub_ieee1275_devalias *alias); |
31 | ||
4b13b216 | 32 | int dev_iterate (struct grub_ieee1275_devalias *alias) |
e56cdf21 | 33 | { |
4b13b216 | 34 | if (! grub_strcmp (alias->type, "block")) |
e56cdf21 | 35 | hook (alias->name); |
d1923dc8 | 36 | else if ((! grub_strcmp (alias->type, "scsi")) |
37 | || (! grub_strcmp (alias->type, "ide")) | |
38 | || (! grub_strcmp (alias->type, "ata"))) | |
39 | /* Search for block-type children of these bus controllers. */ | |
40 | grub_children_iterate (alias->name, dev_iterate); | |
e56cdf21 | 41 | return 0; |
42 | } | |
43 | ||
4b13b216 | 44 | grub_devalias_iterate (dev_iterate); |
e56cdf21 | 45 | return 0; |
46 | } | |
47 | ||
4b13b216 | 48 | static grub_err_t |
49 | grub_ofdisk_open (const char *name, grub_disk_t disk) | |
e56cdf21 | 50 | { |
4b13b216 | 51 | grub_ieee1275_phandle_t dev; |
52 | grub_ieee1275_ihandle_t dev_ihandle = 0; | |
e56cdf21 | 53 | char *devpath = 0; |
54 | /* XXX: This should be large enough for any possible case. */ | |
55 | char prop[64]; | |
e56cdf21 | 56 | int actual; |
57 | ||
d1923dc8 | 58 | devpath = grub_strndup (name, grub_strlen (devpath) + 2); |
e56cdf21 | 59 | if (! devpath) |
4b13b216 | 60 | return grub_errno; |
e56cdf21 | 61 | |
e56cdf21 | 62 | /* To access the complete disk add `:0'. */ |
86f4ae25 | 63 | if (! (grub_ieee1275_flags & GRUB_IEEE1275_NO_PARTITION_0)) |
64 | grub_strcat (devpath, ":0"); | |
65 | ||
4b13b216 | 66 | grub_ieee1275_open (devpath, &dev_ihandle); |
e56cdf21 | 67 | if (! dev_ihandle) |
d1923dc8 | 68 | { |
69 | grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't open device"); | |
70 | goto fail; | |
71 | } | |
e56cdf21 | 72 | |
4b13b216 | 73 | if (grub_ieee1275_finddevice (devpath, &dev)) |
e56cdf21 | 74 | { |
4b13b216 | 75 | grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't read device properties"); |
e56cdf21 | 76 | goto fail; |
77 | } | |
78 | ||
4b13b216 | 79 | if (grub_ieee1275_get_property (dev, "device_type", prop, sizeof (prop), |
e56cdf21 | 80 | &actual)) |
81 | { | |
4b13b216 | 82 | grub_error (GRUB_ERR_BAD_DEVICE, "Can't read the device type"); |
e56cdf21 | 83 | goto fail; |
84 | } | |
85 | ||
4b13b216 | 86 | if (grub_strcmp (prop, "block")) |
e56cdf21 | 87 | { |
4b13b216 | 88 | grub_error (GRUB_ERR_BAD_DEVICE, "Not a block device"); |
e56cdf21 | 89 | goto fail; |
90 | } | |
91 | ||
92 | /* XXX: There is no property to read the number of blocks. There | |
93 | should be a property `#blocks', but it is not there. Perhaps it | |
94 | is possible to use seek for this. */ | |
95 | disk->total_sectors = 0xFFFFFFFFUL; | |
96 | ||
97 | /* XXX: Is it ok to use this? Perhaps it is better to use the path | |
98 | or some property. */ | |
99 | disk->id = dev; | |
100 | ||
101 | /* XXX: Read this, somehow. */ | |
102 | disk->has_partitions = 1; | |
103 | disk->data = (void *) dev_ihandle; | |
104 | ||
105 | fail: | |
d1923dc8 | 106 | if (grub_errno && dev_ihandle) |
4b13b216 | 107 | grub_ieee1275_close (dev_ihandle); |
108 | grub_free (devpath); | |
109 | return grub_errno; | |
e56cdf21 | 110 | } |
111 | ||
112 | static void | |
4b13b216 | 113 | grub_ofdisk_close (grub_disk_t disk) |
e56cdf21 | 114 | { |
4b13b216 | 115 | grub_ieee1275_close ((grub_ieee1275_ihandle_t) disk->data); |
e56cdf21 | 116 | } |
117 | ||
4b13b216 | 118 | static grub_err_t |
119 | grub_ofdisk_read (grub_disk_t disk, unsigned long sector, | |
e56cdf21 | 120 | unsigned long size, char *buf) |
121 | { | |
122 | int status; | |
123 | int actual; | |
124 | unsigned long long pos; | |
125 | ||
126 | pos = (unsigned long long) sector * 512UL; | |
127 | ||
4b13b216 | 128 | grub_ieee1275_seek ((grub_ieee1275_ihandle_t) disk->data, (int) (pos >> 32), |
e56cdf21 | 129 | (int) pos & 0xFFFFFFFFUL, &status); |
130 | if (status != 0) | |
4b13b216 | 131 | return grub_error (GRUB_ERR_READ_ERROR, |
e56cdf21 | 132 | "Seek error, can't seek block %d", sector); |
4b13b216 | 133 | grub_ieee1275_read ((grub_ieee1275_ihandle_t) disk->data, buf, |
e56cdf21 | 134 | size * 512UL, &actual); |
135 | if (actual != actual) | |
4b13b216 | 136 | return grub_error (GRUB_ERR_READ_ERROR, "Read error on block: %d", sector); |
e56cdf21 | 137 | |
138 | return 0; | |
139 | } | |
140 | ||
4b13b216 | 141 | static grub_err_t |
142 | grub_ofdisk_write (grub_disk_t disk __attribute ((unused)), | |
e56cdf21 | 143 | unsigned long sector __attribute ((unused)), |
144 | unsigned long size __attribute ((unused)), | |
145 | const char *buf __attribute ((unused))) | |
146 | { | |
4b13b216 | 147 | return GRUB_ERR_NOT_IMPLEMENTED_YET; |
e56cdf21 | 148 | } |
149 | ||
4b13b216 | 150 | static struct grub_disk_dev grub_ofdisk_dev = |
e56cdf21 | 151 | { |
152 | .name = "ofdisk", | |
97543f08 | 153 | .id = GRUB_DISK_DEVICE_OFDISK_ID, |
4b13b216 | 154 | .iterate = grub_ofdisk_iterate, |
155 | .open = grub_ofdisk_open, | |
156 | .close = grub_ofdisk_close, | |
157 | .read = grub_ofdisk_read, | |
158 | .write = grub_ofdisk_write, | |
e56cdf21 | 159 | .next = 0 |
160 | }; | |
161 | ||
162 | void | |
4b13b216 | 163 | grub_ofdisk_init (void) |
e56cdf21 | 164 | { |
4b13b216 | 165 | grub_disk_dev_register (&grub_ofdisk_dev); |
e56cdf21 | 166 | } |