Indentation fix, cleanup.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / disk / arc / arcdisk.c
blob0cc1993e5fdf3dcd7a417cb55a15acb11a48d70a
1 /* ofdisk.c - Open Firmware disk access. */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2004,2006,2007,2008,2009,2011 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>
22 #include <grub/mm.h>
23 #include <grub/arc/arc.h>
24 #include <grub/i18n.h>
26 static grub_arc_fileno_t last_handle = 0;
27 static char *last_path = NULL;
28 static int handle_writable = 0;
30 static int lnum = 0;
32 struct arcdisk_hash_ent
34 char *devpath;
35 int num;
36 struct arcdisk_hash_ent *next;
39 #define ARCDISK_HASH_SZ 8
40 static struct arcdisk_hash_ent *arcdisk_hash[ARCDISK_HASH_SZ];
42 static int
43 arcdisk_hash_fn (const char *devpath)
45 int hash = 0;
46 while (*devpath)
47 hash ^= *devpath++;
48 return (hash & (ARCDISK_HASH_SZ - 1));
51 static struct arcdisk_hash_ent *
52 arcdisk_hash_find (const char *devpath)
54 struct arcdisk_hash_ent *p = arcdisk_hash[arcdisk_hash_fn (devpath)];
56 while (p)
58 if (!grub_strcmp (p->devpath, devpath))
59 break;
60 p = p->next;
62 return p;
65 static struct arcdisk_hash_ent *
66 arcdisk_hash_add (char *devpath)
68 struct arcdisk_hash_ent *p;
69 struct arcdisk_hash_ent **head = &arcdisk_hash[arcdisk_hash_fn(devpath)];
71 p = grub_malloc (sizeof (*p));
72 if (!p)
73 return NULL;
75 p->devpath = devpath;
76 p->next = *head;
77 p->num = lnum++;
78 *head = p;
79 return p;
83 /* Context for grub_arcdisk_iterate. */
84 struct grub_arcdisk_iterate_ctx
86 grub_disk_dev_iterate_hook_t hook;
87 void *hook_data;
90 /* Helper for grub_arcdisk_iterate. */
91 static int
92 grub_arcdisk_iterate_iter (const char *name,
93 const struct grub_arc_component *comp, void *data)
95 struct grub_arcdisk_iterate_ctx *ctx = data;
97 if (!(comp->type == GRUB_ARC_COMPONENT_TYPE_DISK
98 || comp->type == GRUB_ARC_COMPONENT_TYPE_FLOPPY
99 || comp->type == GRUB_ARC_COMPONENT_TYPE_TAPE))
100 return 0;
101 return ctx->hook (name, ctx->hook_data);
104 static int
105 grub_arcdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
106 grub_disk_pull_t pull)
108 struct grub_arcdisk_iterate_ctx ctx = { hook, hook_data };
110 if (pull != GRUB_DISK_PULL_NONE)
111 return 0;
113 return grub_arc_iterate_devs (grub_arcdisk_iterate_iter, &ctx, 1);
116 #ifdef GRUB_CPU_MIPSEL
117 #define RAW_SUFFIX "partition(0)"
118 #else
119 #define RAW_SUFFIX "partition(10)"
120 #endif
122 static grub_err_t
123 reopen (const char *name, int writable)
125 grub_arc_fileno_t handle;
127 if (last_path && grub_strcmp (last_path, name) == 0
128 && (!writable || handle_writable))
130 grub_dprintf ("arcdisk", "using already opened %s\n", name);
131 return GRUB_ERR_NONE;
133 if (last_path)
135 GRUB_ARC_FIRMWARE_VECTOR->close (last_handle);
136 grub_free (last_path);
137 last_path = NULL;
138 last_handle = 0;
139 handle_writable = 0;
141 if (GRUB_ARC_FIRMWARE_VECTOR->open (name,
142 writable ? GRUB_ARC_FILE_ACCESS_OPEN_RW
143 : GRUB_ARC_FILE_ACCESS_OPEN_RO, &handle))
145 grub_dprintf ("arcdisk", "couldn't open %s\n", name);
146 return grub_error (GRUB_ERR_IO, "couldn't open %s", name);
148 handle_writable = writable;
149 last_path = grub_strdup (name);
150 if (!last_path)
151 return grub_errno;
152 last_handle = handle;
153 grub_dprintf ("arcdisk", "opened %s\n", name);
154 return GRUB_ERR_NONE;
157 static grub_err_t
158 grub_arcdisk_open (const char *name, grub_disk_t disk)
160 char *fullname;
161 grub_err_t err;
162 grub_arc_err_t r;
163 struct grub_arc_fileinfo info;
164 struct arcdisk_hash_ent *hash;
166 if (grub_memcmp (name, "arc/", 4) != 0)
167 return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not arc device");
168 fullname = grub_arc_alt_name_to_norm (name, RAW_SUFFIX);
169 disk->data = fullname;
170 grub_dprintf ("arcdisk", "opening %s\n", fullname);
172 hash = arcdisk_hash_find (fullname);
173 if (!hash)
174 hash = arcdisk_hash_add (fullname);
175 if (!hash)
176 return grub_errno;
178 err = reopen (fullname, 0);
179 if (err)
180 return err;
182 r = GRUB_ARC_FIRMWARE_VECTOR->getfileinformation (last_handle, &info);
183 if (r)
185 grub_uint64_t res = 0;
186 int i;
188 grub_dprintf ("arcdisk", "couldn't retrieve size: %ld\n", r);
189 for (i = 40; i >= 9; i--)
191 grub_uint64_t pos = res | (1ULL << i);
192 char buf[512];
193 long unsigned count = 0;
194 grub_dprintf ("arcdisk",
195 "seek to 0x%" PRIxGRUB_UINT64_T "\n", pos);
196 if (GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0))
197 continue;
198 if (GRUB_ARC_FIRMWARE_VECTOR->read (last_handle, buf,
199 0x200, &count))
200 continue;
201 if (count == 0)
202 continue;
203 res |= (1ULL << i);
205 grub_dprintf ("arcdisk",
206 "determined disk size 0x%" PRIxGRUB_UINT64_T "\n", res);
207 disk->total_sectors = (res + 0x200) >> 9;
209 else
210 disk->total_sectors = (info.end >> 9);
212 disk->id = hash->num;
213 return GRUB_ERR_NONE;
216 static void
217 grub_arcdisk_close (grub_disk_t disk)
219 grub_free (disk->data);
222 static grub_err_t
223 grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
224 grub_size_t size, char *buf)
226 grub_err_t err;
227 grub_uint64_t pos = sector << 9;
228 unsigned long count;
229 grub_uint64_t totl = size << 9;
230 grub_arc_err_t r;
232 err = reopen (disk->data, 0);
233 if (err)
234 return err;
235 r = GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0);
236 if (r)
238 grub_dprintf ("arcdisk", "seek to 0x%" PRIxGRUB_UINT64_T " failed: %ld\n",
239 pos, r);
240 return grub_error (GRUB_ERR_IO, "couldn't seek");
243 while (totl)
245 if (GRUB_ARC_FIRMWARE_VECTOR->read (last_handle, buf,
246 totl, &count))
247 return grub_error (GRUB_ERR_READ_ERROR,
248 N_("failure reading sector 0x%llx "
249 "from `%s'"),
250 (unsigned long long) sector,
251 disk->name);
252 totl -= count;
253 buf += count;
256 return GRUB_ERR_NONE;
259 static grub_err_t
260 grub_arcdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
261 grub_size_t size, const char *buf)
263 grub_err_t err;
264 grub_uint64_t pos = sector << 9;
265 unsigned long count;
266 grub_uint64_t totl = size << 9;
267 grub_arc_err_t r;
269 err = reopen (disk->data, 1);
270 if (err)
271 return err;
272 r = GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0);
273 if (r)
275 grub_dprintf ("arcdisk", "seek to 0x%" PRIxGRUB_UINT64_T " failed: %ld\n",
276 pos, r);
277 return grub_error (GRUB_ERR_IO, "couldn't seek");
280 while (totl)
282 if (GRUB_ARC_FIRMWARE_VECTOR->write (last_handle, buf,
283 totl, &count))
284 return grub_error (GRUB_ERR_WRITE_ERROR, N_("failure writing sector 0x%llx "
285 "to `%s'"),
286 (unsigned long long) sector,
287 disk->name);
288 totl -= count;
289 buf += count;
292 return GRUB_ERR_NONE;
295 static struct grub_disk_dev grub_arcdisk_dev =
297 .name = "arcdisk",
298 .id = GRUB_DISK_DEVICE_ARCDISK_ID,
299 .iterate = grub_arcdisk_iterate,
300 .open = grub_arcdisk_open,
301 .close = grub_arcdisk_close,
302 .read = grub_arcdisk_read,
303 .write = grub_arcdisk_write,
304 .next = 0
307 void
308 grub_arcdisk_init (void)
310 grub_disk_dev_register (&grub_arcdisk_dev);
313 void
314 grub_arcdisk_fini (void)
316 if (last_path)
318 GRUB_ARC_FIRMWARE_VECTOR->close (last_handle);
319 grub_free (last_path);
320 last_path = NULL;
321 last_handle = 0;
324 grub_disk_dev_unregister (&grub_arcdisk_dev);