Ok, finally GRUB works also on my workstation. These are the changes that allow GRUB to properly handle "," characters in OF path names.
As we discussed about a month ago, when a "," appears in an OF path name we escape it with "\". So all of the real work is escaping OF paths as they are given to GRUB, and then un-escaping them when ofdisk tries to open them. Committed. PS: I plan to spend the next few days testing what we have now on a variety of sparc64 systems to make sure all of the most obvious problems get shaken out. 2009-05-04 David S. Miller <da...@davemloft.net> * disk/ieee1275/ofdisk.c (compute_dev_path): New. (grub_ofdisk_open): Use it to un-escape "," characters. * kern/disk.c (find_part_sep): New. (grub_disk_open): Use it to find the first non-escaped ',' character in the disk name. * util/ieee1275/devicemap.c (escape_of_path): New. (grub_util_emit_devicemap_entry): Use it. * util/sparc64/ieee1275/grub-install.in: Update script to strip partition specifiers properly by not triggering on '\' escaped ',' characters. Index: disk/ieee1275/ofdisk.c =================================================================== --- disk/ieee1275/ofdisk.c (revision 2188) +++ disk/ieee1275/ofdisk.c (working copy) @@ -115,6 +115,38 @@ return grub_devalias_iterate (dev_iterate); } +static char * +compute_dev_path (const char *name) +{ + char *devpath = grub_malloc (grub_strlen (name) + 2); + char *p, c; + + if (!devpath) + return NULL; + + /* Un-escape commas. */ + p = devpath; + while ((c = *name++) != '\0') + { + if (c == '\\' && *name == ',') + { + *p++ = ','; + name++; + } + else + *p++ = c; + } + + if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0)) + { + *p++ = ':'; + *p++ = '0'; + } + *p++ = '\0'; + + return devpath; +} + static grub_err_t grub_ofdisk_open (const char *name, grub_disk_t disk) { @@ -126,14 +158,10 @@ char prop[64]; grub_ssize_t actual; - devpath = grub_strndup (name, grub_strlen (name) + 2); + devpath = compute_dev_path (name); if (! devpath) return grub_errno; - /* To access the complete disk add `:0'. */ - if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0)) - grub_strcat (devpath, ":0"); - op = ofdisk_hash_find (devpath); if (!op) op = ofdisk_hash_add (devpath); Index: kern/disk.c =================================================================== --- kern/disk.c (revision 2185) +++ kern/disk.c (working copy) @@ -215,10 +215,28 @@ return 0; } +/* Return the location of the first ',', if any, which is not + escaped by a '\'. */ +static const char * +find_part_sep (const char *name) +{ + const char *p = name; + char c; + + while ((c = *p++) != '\0') + { + if (c == '\\' && *p == ',') + p++; + else if (c == ',') + return p - 1; + } + return NULL; +} + grub_disk_t grub_disk_open (const char *name) { - char *p; + const char *p; grub_disk_t disk; grub_disk_dev_t dev; char *raw = (char *) name; @@ -238,7 +256,7 @@ if (! disk->name) goto fail; - p = grub_strchr (name, ','); + p = find_part_sep (name); if (p) { grub_size_t len = p - name; Index: util/sparc64/ieee1275/grub-install.in =================================================================== --- util/sparc64/ieee1275/grub-install.in (revision 2185) +++ util/sparc64/ieee1275/grub-install.in (working copy) @@ -237,8 +237,8 @@ grub_drive="`$grub_probe --target=drive --device ${grub_device}`" # Strip partition number - install_drive="`echo ${install_drive} | sed -e s/,[0-9]*//g`" - grub_drive="`echo ${grub_drive} | sed -e s/,[0-9]*//g`" + install_drive="`echo ${install_drive} | sed -e s/\([^\]\),[0-9]*/\1/g`" + grub_drive="`echo ${grub_drive} | sed -e s/\([^\]\),[0-9]*/\1/g`" if [ "x${grub_drive}" != "x${install_drive}" ] ; then uuid="`$grub_probe --target=fs_uuid --device ${grub_device}`" if [ "x${uuid}" = "x" ] ; then Index: util/sparc64/ieee1275/grub-setup.c =================================================================== --- util/sparc64/ieee1275/grub-setup.c (revision 2185) +++ util/sparc64/ieee1275/grub-setup.c (working copy) @@ -56,7 +56,7 @@ * device. It also needs to know the initial block number of * 'core' (which is 'diskboot' concatenated with 'kernel' and * all the modules, this is created by grub-mkimage). This resulting - * 'boot' image is 512 bytes in size and is placed in the first block + * 'boot' image is 512 bytes in size and is placed in the second block * of a partition. * * The initial 'diskboot' block acts as a loader for the actual GRUB @@ -100,6 +100,28 @@ fflush (stdout); } +static char *compute_dest_ofpath (const char *dest) +{ + int len = strlen (dest); + char *res, *p, c; + + res = xmalloc (len); + p = res; + while ((c = *dest++) != '\0') + { + if (c == '\\' && *dest == ',') + { + *p++ = ','; + dest++; + } + else + *p++ = c; + } + *p++ = '\0'; + + return res; +} + static void setup (const char *prefix, const char *dir, const char *boot_file, const char *core_file, @@ -110,7 +132,7 @@ size_t boot_size, core_size; grub_uint16_t core_sectors; grub_device_t root_dev, dest_dev; - char *boot_devpath; + char *boot_devpath, *dest_ofpath; grub_disk_addr_t *kernel_sector; struct boot_blocklist *first_block, *block; char *tmp_img; @@ -170,6 +192,8 @@ last_length = length; } + dest_ofpath = compute_dest_ofpath (dest); + /* Read the boot image by the OS service. */ boot_path = grub_util_get_path (dir, boot_file); boot_size = grub_util_get_image_size (boot_path); @@ -202,7 +226,8 @@ + GRUB_DISK_SECTOR_SIZE - sizeof (*block)); - grub_util_info ("root is '%s' and dest is '%s'", root, dest); + grub_util_info ("root is '%s', dest is '%s', and dest_ofpath is '%s'", + root, dest, dest_ofpath); /* Open the root device and the destination device. */ grub_util_info ("Opening root"); @@ -330,7 +355,7 @@ *kernel_sector = grub_cpu_to_be64 (first_sector); - strcpy(boot_devpath, dest); + strcpy(boot_devpath, dest_ofpath); grub_util_info ("boot device path %s, prefix is %s, dest is %s", boot_devpath, prefix, dest); Index: util/ieee1275/devicemap.c =================================================================== --- util/ieee1275/devicemap.c (revision 2185) +++ util/ieee1275/devicemap.c (working copy) @@ -1,13 +1,47 @@ #include <stdio.h> +#include <string.h> #include <grub/types.h> #include <grub/util/deviceiter.h> #include <grub/util/ofpath.h> +#include <grub/util/misc.h> +/* Since OF path names can have "," characters in them, and GRUB + internally uses "," to indicate partitions (unlike OF which uses + ":" for this purpose) we escape such commas. */ + +static char * +escape_of_path (const char *orig_path) +{ + char *new_path, *d, c; + const char *p; + + if (!strchr (orig_path, ',')) + return (char *) orig_path; + + new_path = xmalloc (strlen (orig_path) * 2); + + p = orig_path; + d = new_path; + while ((c = *p++) != '\0') + { + if (c == ',') + *d++ = '\\'; + *d++ = c; + } + + free ((char *) orig_path); + + return new_path; +} + void grub_util_emit_devicemap_entry (FILE *fp, char *name, int is_floppy UNUSED, int *num_fd UNUSED, int *num_hd UNUSED) { - const char *ofpath = grub_util_devname_to_ofpath (name); + const char *orig_path = grub_util_devname_to_ofpath (name); + char *ofpath = escape_of_path (orig_path); fprintf(fp, "(%s)\t%s\n", ofpath, name); + + free (ofpath); } _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel