Marco, I believe I addressed all your comments in my mail on 23 Feb 2005. I have implemented your suggestions, with the exception of checking the device node property lengths, as this requires modifying many callers elsewhere in the code.
I will commit this in a couple days if I don't hear any complaints. -Hollis 2005-02-13 Hollis Blanchard <[EMAIL PROTECTED]> * include/grub/powerpc/ieee1275/ieee1275.h (grub_ieee1275_get_dev_encoding): New prototype. (grub_ieee1275_get_filename): Likewise. * kern/powerpc/ieee1275/init.c (grub_translate_ieee175_path): New function. (grub_set_prefix): Likewise. (grub_machine_init): Call grub_set_prefix. * kern/powerpc/ieee1275/openfw.c (grub_parse_type): New enum. (grub_ieee1275_get_devargs): New function. (grub_ieee1275_get_devname): Likewise. (grub_ieee1275_parse_args): Likewise. (grub_ieee1275_get_filename): Likewise. (grub_ieee1275_get_dev_encoding): Likewise. Index: include/grub/powerpc/ieee1275/ieee1275.h =================================================================== RCS file: /cvsroot/grub/grub2/include/grub/powerpc/ieee1275/ieee1275.h,v retrieving revision 1.15 diff -u -p -r1.15 ieee1275.h --- include/grub/powerpc/ieee1275/ieee1275.h 26 Mar 2005 17:34:50 -0000 1.15 +++ include/grub/powerpc/ieee1275/ieee1275.h 14 Apr 2005 02:57:01 -0000 @@ -134,5 +134,7 @@ void EXPORT_FUNC(abort) (void); void EXPORT_FUNC (grub_reboot) (void); void EXPORT_FUNC (grub_halt) (void); +char *EXPORT_FUNC(grub_ieee1275_get_dev_encoding) (const char *path); +char *EXPORT_FUNC(grub_ieee1275_get_filename) (const char *path); #endif /* ! GRUB_IEEE1275_MACHINE_HEADER */ Index: kern/powerpc/ieee1275/init.c =================================================================== RCS file: /cvsroot/grub/grub2/kern/powerpc/ieee1275/init.c,v retrieving revision 1.14 diff -u -p -r1.14 init.c --- kern/powerpc/ieee1275/init.c 26 Mar 2005 17:34:50 -0000 1.14 +++ kern/powerpc/ieee1275/init.c 14 Apr 2005 02:57:01 -0000 @@ -46,6 +46,68 @@ abort (void) for (;;); } +/* Translate an OF filesystem path (separated by backslashes), into a GRUB + path (separated by forward slashes). */ +static void +grub_translate_ieee1275_path(char *filepath) +{ + char *backslash; + + backslash = grub_strchr (filepath, '\\'); + while (backslash != 0) + { + *backslash = '/'; + backslash = grub_strchr (filepath, '\\'); + } +} + +static void +grub_set_prefix (void) +{ + char bootpath[64]; /* XXX check length */ + char *filename; + char *prefix; + grub_ieee1275_phandle_t chosen; + + grub_ieee1275_finddevice ("/chosen", &chosen); + if (grub_ieee1275_get_property (chosen, "bootpath", &bootpath, + sizeof (bootpath), 0)) + { + /* Should never happen. */ + grub_printf ("/chosen/bootpath property missing!\n"); + grub_env_set ("prefix", ""); + } + + /* Transform an OF device path to a GRUB path. */ + + prefix = grub_ieee1275_get_dev_encoding (bootpath); + + filename = grub_ieee1275_get_filename (bootpath); + if (filename) + { + char *newprefix; + char *lastslash = grub_strrchr (filename, '\\'); + + /* Truncate at last directory. */ + if (lastslash) + { + *lastslash = '\0'; + grub_translate_ieee1275_path (filename); + + newprefix = grub_malloc (grub_strlen (prefix) + + grub_strlen (filename)); + grub_sprintf (newprefix, "%s%s", prefix, filename); + grub_free (prefix); + prefix = newprefix; + } + } + + grub_env_set ("prefix", prefix); + + grub_free (filename); + grub_free (prefix); +} + void grub_machine_init (void) { @@ -65,7 +127,7 @@ grub_machine_init (void) } grub_mm_init_region ((void *) grub_heap_start, grub_heap_len); - grub_env_set ("prefix", ""); + grub_set_prefix (); grub_ofdisk_init (); } Index: kern/powerpc/ieee1275/openfw.c =================================================================== RCS file: /cvsroot/grub/grub2/kern/powerpc/ieee1275/openfw.c,v retrieving revision 1.8 diff -u -p -r1.8 openfw.c --- kern/powerpc/ieee1275/openfw.c 26 Mar 2005 17:34:50 -0000 1.8 +++ kern/powerpc/ieee1275/openfw.c 14 Apr 2005 02:57:01 -0000 @@ -23,6 +23,12 @@ #include <grub/mm.h> #include <grub/machine/ieee1275.h> +enum grub_ieee1275_parse_type +{ + GRUB_PARSE_FILENAME, + GRUB_PARSE_PARTITION, +}; + /* Walk children of 'devpath', calling hook for each. */ grub_err_t grub_children_iterate (char *devpath, @@ -64,7 +70,7 @@ grub_children_iterate (char *devpath, if (actual == -1) continue; - grub_sprintf(fullname, "%s/%s", devpath, childname); + grub_sprintf (fullname, "%s/%s", devpath, childname); alias.type = childtype; alias.path = childpath; @@ -200,6 +206,138 @@ grub_claimmap (grub_addr_t addr, grub_si return 0; } +/* Get the device arguments of the Open Firmware device specifier `path'. */ +static char * +grub_ieee1275_get_devargs (const char *path) +{ + char *colon = grub_strchr (path, ':'); + char *end; + + if (! colon) + return 0; + + end = colon + grub_strlen (colon); + + return grub_strndup (colon + 1, end - colon); +} + +/* Get the device path of the Open Firmware device specifier `path'. */ +static char * +grub_ieee1275_get_devname (const char *path) +{ + char *colon = grub_strchr (path, ':'); + + if (! colon) + return grub_strdup (path); + + return grub_strndup (path, (grub_size_t)(colon - path)); +} + +static char * +grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type type) +{ + char type[64]; /* XXX check size. */ + char *device = grub_ieee1275_get_devname (path); + char *args = grub_ieee1275_get_devargs (path); + char *ret = 0; + grub_ieee1275_phandle_t dev; + + if (!args) + /* Shouldn't happen. */ + return 0; + + /* We need to know what type of device it is in order to parse the full + file path properly. */ + if (grub_ieee1275_finddevice (device, &dev)) + { + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Device %s not found\n", device); + goto fail; + } + if (grub_ieee1275_get_property (dev, "device_type", &type, sizeof type, 0)) + { + grub_error (GRUB_ERR_UNKNOWN_DEVICE, + "Device %s lacks a device_type property\n", device); + goto fail; + } + + if (!grub_strcmp ("block", type)) + { + /* The syntax of the device arguments is defined in the CHRP and PReP + IEEE1275 bindings: "[partition][,[filename]]". */ + char *comma = grub_strchr (args, ','); + + if (field == GRUB_PARSE_FILENAME) + { + if (comma) + { + char *filepath = comma + 1; + + ret = grub_malloc (grub_strlen (filepath) + 1); + /* Make sure filepath has leading backslash. */ + if (filepath[0] != '\\') + grub_sprintf (ret, "\\%s", filepath); + else + grub_strcpy (ret, filepath); + } + } + else if (field == GRUB_PARSE_PARTITION) + { + if (!comma) + ret = grub_strdup (args); + else + ret = grub_strndup (args, (grub_size_t)(comma - args)); + } + } + else + { + /* XXX Handle net devices by configuring & registering a grub_net_dev + here, then return its name? + Example path: "net:<server ip>,<file name>,<client ip>,<gateway + ip>,<bootp retries>,<tftp retries>". */ + grub_printf ("Unsupported type %s for device %s\n", type, device); + } + +fail: + grub_free (device); + grub_free (args); + return ret; +} + +char * +grub_ieee1275_get_filename (const char *path) +{ + return grub_ieee1275_parse_args (path, GRUB_PARSE_FILENAME); +} + +char * +grub_ieee1275_get_dev_encoding (const char *path) +{ + char *device = grub_ieee1275_get_devname (path); + char *partition = grub_ieee1275_parse_args (path, GRUB_PARSE_PARTITION); + char *encoding; + + if (partition) + { + unsigned int partno = grub_strtoul (partition, 0, 0); + partno--; /* GRUB partition numbering is 0-based. */ + + /* Assume partno will require less than five bytes to encode (not + including punctuation). */ + encoding = grub_malloc (grub_strlen (device) + 3 + 5); + grub_sprintf (encoding, "(%s,%d)", device, partno); + } + else + { + encoding = grub_malloc (grub_strlen (device) + 2); + grub_sprintf (encoding, "(%s)", device); + } + + grub_free (partition); + grub_free (device); + + return encoding; +} + void grub_reboot (void) { Index: loader/powerpc/ieee1275/linux.c =================================================================== RCS file: /cvsroot/grub/grub2/loader/powerpc/ieee1275/linux.c,v retrieving revision 1.6 diff -u -p -r1.6 linux.c --- loader/powerpc/ieee1275/linux.c 14 Feb 2005 18:41:33 -0000 1.6 +++ loader/powerpc/ieee1275/linux.c 14 Apr 2005 02:57:01 -0000 @@ -55,7 +55,7 @@ grub_linux_boot (void) /* Set the command line arguments. */ grub_ieee1275_set_property (chosen, "bootargs", linux_args, grub_strlen (linux_args) + 1, &actual); - + /* Boot the kernel. */ linuxmain = (kernel_entry_t) linux_addr; linuxmain ((void *) initrd_addr, initrd_size, grub_ieee1275_entry_fn, 0, 0); _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel