make the linux-ppc packags be in synch with other platforms
[tangerine.git] / arch / common / boot / grub2 / kern / sparc64 / ieee1275 / openfw.c
blobfe9ee96ce8d6a354360cb9eb7ae337593961d402
1 /* openfw.c -- Open firmware support functions. */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2003,2004,2005,2007 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/err.h>
21 #include <grub/misc.h>
22 #include <grub/mm.h>
23 #include <grub/machine/kernel.h> /* Needed ? */
24 #include <grub/ieee1275/ieee1275.h>
26 enum grub_ieee1275_parse_type
28 GRUB_PARSE_FILENAME,
29 GRUB_PARSE_PARTITION,
32 /* Walk children of 'devpath', calling hook for each. */
33 grub_err_t
34 grub_children_iterate (char *devpath,
35 int (*hook) (struct grub_ieee1275_devalias *alias))
37 grub_ieee1275_phandle_t dev;
38 grub_ieee1275_phandle_t child;
40 grub_ieee1275_finddevice (devpath, &dev);
41 if (((signed) dev) == -1)
42 return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Unknown device");
44 grub_ieee1275_child (dev, &child);
45 if (((signed) child) == -1)
46 return grub_error (GRUB_ERR_BAD_DEVICE, "Device has no children");
50 /* XXX: Don't use hardcoded path lengths. */
51 char childtype[64];
52 char childpath[64];
53 char childname[64];
54 char fullname[64];
55 struct grub_ieee1275_devalias alias;
56 grub_ssize_t actual;
58 grub_ieee1275_get_property (child, "device_type", childtype,
59 sizeof childtype, &actual);
60 if (actual == -1)
61 continue;
63 grub_ieee1275_package_to_path (child, childpath, sizeof childpath,
64 &actual);
65 if (actual == -1)
66 continue;
68 grub_ieee1275_get_property (child, "name", childname,
69 sizeof childname, &actual);
70 if (actual == -1)
71 continue;
73 grub_sprintf (fullname, "%s/%s", devpath, childname);
75 alias.type = childtype;
76 alias.path = childpath;
77 alias.name = fullname;
78 hook (&alias);
80 while (grub_ieee1275_peer (child, &child));
82 return 0;
85 /* Iterate through all device aliases. This function can be used to
86 find a device of a specific type. */
87 grub_err_t
88 grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias))
90 grub_ieee1275_phandle_t devalias;
91 char aliasname[32];
92 grub_ssize_t actual;
93 grub_ieee1275_cell_t flags;
94 struct grub_ieee1275_devalias alias;
96 if (grub_ieee1275_finddevice ("/aliases", &devalias))
97 return -1;
99 aliasname[0] = '\0';
101 while (grub_ieee1275_next_property (devalias, aliasname, aliasname, &flags) != -1
102 && ((signed) flags) != -1 )
104 grub_ieee1275_phandle_t dev;
105 grub_ssize_t pathlen, typelen;
106 char *devpath, *devtype;
108 grub_dprintf ("devalias", "devalias name = %s\n", aliasname);
110 /* The property `name' is a special case we should skip. */
111 if (!grub_strcmp (aliasname, "name"))
112 continue;
114 grub_ieee1275_get_property_length (devalias, aliasname, &pathlen);
115 devpath = grub_malloc (pathlen);
116 if (! devpath)
117 return grub_errno;
119 if (grub_ieee1275_get_property (devalias, aliasname, devpath, pathlen,
120 &actual))
122 grub_dprintf ("devalias", "get_property (%s) failed\n", aliasname);
123 grub_free (devpath);
124 continue;
127 if (grub_ieee1275_finddevice (devpath, &dev) || ((signed) dev) == -1)
129 grub_dprintf ("devalias", "finddevice (%s) failed\n", devpath);
130 grub_free (devpath);
131 continue;
134 grub_ieee1275_get_property_length (dev, "device_type", &typelen);
135 devtype = grub_malloc (typelen);
136 if (! devtype)
138 grub_free (devpath);
139 return grub_errno;
141 if (grub_ieee1275_get_property (dev, "device_type", devtype, typelen, &actual))
143 grub_dprintf ("devalias", "get device type failed\n");
144 grub_free (devtype);
145 grub_free (devpath);
146 continue;
149 alias.name = aliasname;
150 alias.path= devpath;
151 alias.type = devtype;
152 if((*hook) (&alias))
154 grub_free (devtype);
155 grub_free (devpath);
156 break;
159 grub_free (devtype);
160 grub_free (devpath);
163 return 0;
166 /* FIXME (sparc64) */
167 #if 0
168 /* Call the "map" method of /chosen/mmu. */
169 static int
170 grub_map (grub_addr_t phys, grub_addr_t virt, grub_uint32_t size,
171 grub_uint8_t mode)
173 struct map_args {
174 struct grub_ieee1275_common_hdr common;
175 char *method;
176 grub_ieee1275_ihandle_t ihandle;
177 grub_uint32_t mode;
178 grub_uint32_t size;
179 grub_uint32_t virt;
180 grub_uint32_t phys;
181 int catch_result;
182 } args;
183 grub_ieee1275_ihandle_t mmu;
184 grub_ssize_t len;
186 grub_ieee1275_get_integer_property (grub_ieee1275_chosen, "mmu", &mmu, sizeof mmu,
187 &len);
188 if (len != sizeof mmu)
189 return -1;
191 INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 1);
192 args.method = "map";
193 args.ihandle = mmu;
194 args.phys = phys;
195 args.virt = virt;
196 args.size = size;
197 args.mode = mode; /* Format is WIMG0PP. */
199 if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
200 return -1;
202 return args.catch_result;
204 #endif
207 grub_claimmap (grub_addr_t addr, grub_size_t size)
209 if (grub_ieee1275_claim (addr, size, 0, 0))
210 return -1;
211 return 0;
214 /* Get the device arguments of the Open Firmware node name `path'. */
215 static char *
216 grub_ieee1275_get_devargs (const char *path)
218 char *colon = grub_strchr (path, ':');
220 if (! colon)
221 return 0;
223 return grub_strdup (colon + 1);
226 /* Get the device path of the Open Firmware node name `path'. */
227 static char *
228 grub_ieee1275_get_devname (const char *path)
230 char *colon = grub_strchr (path, ':');
231 char *newpath = 0;
232 int pathlen = grub_strlen (path);
233 auto int match_alias (struct grub_ieee1275_devalias *alias);
235 int match_alias (struct grub_ieee1275_devalias *curalias)
237 /* briQ firmware can change capitalization in /chosen/bootpath. */
238 if (! grub_strncasecmp (curalias->path, path, pathlen))
240 newpath = grub_strndup (curalias->name, grub_strlen (curalias->name));
241 return 1;
244 return 0;
247 if (colon)
248 pathlen = (int)(colon - path);
250 /* Try to find an alias for this device. */
251 grub_devalias_iterate (match_alias);
253 if (! newpath)
254 newpath = grub_strdup (path);
256 return newpath;
259 static char *
260 grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype)
262 char type[64]; /* XXX check size. */
263 char *device = grub_ieee1275_get_devname (path);
264 char *args = grub_ieee1275_get_devargs (path);
265 char *ret = 0;
266 grub_ieee1275_phandle_t dev;
268 if (!args)
269 /* Shouldn't happen. */
270 return 0;
272 /* We need to know what type of device it is in order to parse the full
273 file path properly. */
274 if (grub_ieee1275_finddevice (device, &dev))
276 grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Device %s not found\n", device);
277 goto fail;
279 if (grub_ieee1275_get_property (dev, "device_type", type, sizeof type, 0))
281 grub_error (GRUB_ERR_UNKNOWN_DEVICE,
282 "Device %s lacks a device_type property\n", device);
283 goto fail;
286 if (!grub_strcmp ("block", type))
288 /* The syntax of the device arguments is defined in the CHRP and PReP
289 IEEE1275 bindings: "[partition][,[filename]]". */
290 char *comma = grub_strchr (args, ',');
292 if (ptype == GRUB_PARSE_FILENAME)
294 if (comma)
296 char *filepath = comma + 1;
298 ret = grub_malloc (grub_strlen (filepath) + 1);
299 /* Make sure filepath has leading backslash. */
300 if (filepath[0] != '\\')
301 grub_sprintf (ret, "\\%s", filepath);
302 else
303 grub_strcpy (ret, filepath);
306 else if (ptype == GRUB_PARSE_PARTITION)
308 if (!comma)
309 ret = grub_strdup (args);
310 else
311 ret = grub_strndup (args, (grub_size_t)(comma - args));
314 else
316 /* XXX Handle net devices by configuring & registering a grub_net_dev
317 here, then return its name?
318 Example path: "net:<server ip>,<file name>,<client ip>,<gateway
319 ip>,<bootp retries>,<tftp retries>". */
320 grub_printf ("Unsupported type %s for device %s\n", type, device);
323 fail:
324 grub_free (device);
325 grub_free (args);
326 return ret;
329 char *
330 grub_ieee1275_get_filename (const char *path)
332 return grub_ieee1275_parse_args (path, GRUB_PARSE_FILENAME);
335 /* Convert a device name from IEEE1275 syntax to GRUB syntax. */
336 char *
337 grub_ieee1275_encode_devname (const char *path)
339 char *device = grub_ieee1275_get_devname (path);
340 char *partition = grub_ieee1275_parse_args (path, GRUB_PARSE_PARTITION);
341 char *encoding;
343 if (partition)
345 unsigned int partno = grub_strtoul (partition, 0, 0);
347 /* Assume partno will require less than five bytes to encode. */
348 encoding = grub_malloc (grub_strlen (device) + 3 + 5);
349 grub_sprintf (encoding, "(%s,%d)", device, partno);
351 else
353 encoding = grub_malloc (grub_strlen (device) + 2);
354 grub_sprintf (encoding, "(%s)", device);
357 grub_free (partition);
358 grub_free (device);
360 return encoding;
363 void
364 grub_reboot (void)
366 grub_ieee1275_interpret ("reset-all", 0);
369 void
370 grub_halt (void)
372 grub_ieee1275_interpret ("power-off", 0);