From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1D0O3r-0004e7-Sz for mharc-grub-devel@gnu.org; Sun, 13 Feb 2005 13:01:36 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1D0O0W-0003Kd-6P for grub-devel@gnu.org; Sun, 13 Feb 2005 12:58:08 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1D0O0J-0003G5-Sd for grub-devel@gnu.org; Sun, 13 Feb 2005 12:57:56 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1D0O0J-0003Av-Gj for grub-devel@gnu.org; Sun, 13 Feb 2005 12:57:55 -0500 Received: from [207.217.121.249] (helo=pop-a065d05.pas.sa.earthlink.net) by monty-python.gnu.org with esmtp (Exim 4.34) id 1D0NQ3-00045A-Nf for grub-devel@gnu.org; Sun, 13 Feb 2005 12:20:28 -0500 Received: from user-0vvde2g.cable.mindspring.com ([63.246.184.80] helo=miracle) by pop-a065d05.pas.sa.earthlink.net with esmtp (Exim 3.33 #1) id 1D0NQ2-0003D6-00 for grub-devel@gnu.org; Sun, 13 Feb 2005 09:20:26 -0800 Received: from hollis by miracle with local (Exim 3.36 #1 (Debian)) id 1D0N1J-0001DM-00 for ; Sun, 13 Feb 2005 10:54:53 -0600 Date: Sun, 13 Feb 2005 10:54:52 -0600 To: grub-devel@gnu.org Message-ID: <20050213165452.GA4503@miracle> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.6+20040907i From: Hollis Blanchard Subject: [patch] set prefix on PPC X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: The development of GRUB 2 List-Id: The development of GRUB 2 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 13 Feb 2005 18:01:34 -0000 Any comments on this patch? This code sets the GRUB "prefix" environment variable from the OF /chosen/bootpath property. It must therefore translate between the two syntaxes. I believe most of this code could be moved to a kern/ieee1275/device.c file, but that can wait until there is another supported OF platform. I have verified that this works (a config file is loaded) from disk, and netbooting is not broken. The subdirectory stuff works as well. -Hollis 2005-02-13 Hollis Blanchard * include/grub/powerpc/ieee1275/ieee1275.h (grub_ieee1275_get_dev_encoding): New prototype. (grub_ieee1275_get_filename): Likewise. * kern/powerpc/ieee1275/init.c (translate_path): New function. (grub_set_prefix): Likewise. (grub_machine_init): Call grub_set_prefix. * kern/powerpc/ieee1275/openfw.c (GRUB_PARSE_FILENAME): New constant. (GRUB_PARSE_PARTITION): Likewise. (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.14 diff -u -p -r1.14 ieee1275.h --- include/grub/powerpc/ieee1275/ieee1275.h 31 Jan 2005 21:28:34 -0000 1.14 +++ include/grub/powerpc/ieee1275/ieee1275.h 13 Feb 2005 17:16:17 -0000 @@ -132,5 +132,8 @@ int EXPORT_FUNC(grub_claimmap) (grub_add void EXPORT_FUNC(abort) (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.13 diff -u -p -r1.13 init.c --- kern/powerpc/ieee1275/init.c 4 Jan 2005 14:01:45 -0000 1.13 +++ kern/powerpc/ieee1275/init.c 13 Feb 2005 17:16:17 -0000 @@ -42,6 +42,68 @@ abort (void) for (;;); } +/* Translate an OF filesystem path (separated by backslashes), into a GRUB + path (separated by forward slashes). */ +static void +translate_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'; + translate_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 *) heap_start, 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.7 diff -u -p -r1.7 openfw.c --- kern/powerpc/ieee1275/openfw.c 3 Jan 2005 17:44:25 -0000 1.7 +++ kern/powerpc/ieee1275/openfw.c 13 Feb 2005 17:16:17 -0000 @@ -23,6 +23,11 @@ #include #include +enum { + GRUB_PARSE_FILENAME, + GRUB_PARSE_PARTITION, +}; + /* Walk children of 'devpath', calling hook for each. */ grub_err_t grub_children_iterate (char *devpath, @@ -64,7 +69,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; @@ -199,3 +204,133 @@ 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, int field) +{ + 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 out; + } + 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 out; + } + + if (!grub_strcmp ("block", type)) + { + /* Example: "disk:,". */ + 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:,,,,,". */ + grub_printf ("Unsupported type %s for device %s\n", type, device); + } + +out: + 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. */ + + /* XXX Assume partno will only require two bytes? */ + encoding = grub_malloc (grub_strlen (device) + 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; +}