From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1GcbXn-0008Qe-Db for mharc-grub-devel@gnu.org; Wed, 25 Oct 2006 01:43:15 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1GcbXl-0008QN-Qm for grub-devel@gnu.org; Wed, 25 Oct 2006 01:43:13 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1GcbXk-0008QB-He for grub-devel@gnu.org; Wed, 25 Oct 2006 01:43:12 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1GcbXk-0008Q8-Bw for grub-devel@gnu.org; Wed, 25 Oct 2006 01:43:12 -0400 Received: from [134.134.136.24] (helo=mga09.intel.com) by monty-python.gnu.org with esmtp (Exim 4.52) id 1GcbXk-0002dG-29 for grub-devel@gnu.org; Wed, 25 Oct 2006 01:43:12 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by mga09.intel.com with ESMTP; 24 Oct 2006 22:43:11 -0700 Received: from bmao-mobl.ccr.corp.intel.com (HELO [10.239.22.151]) ([10.239.22.151]) by orsmga001.jf.intel.com with ESMTP; 24 Oct 2006 22:43:10 -0700 X-ExtLoop1: 1 X-IronPort-AV: i="4.09,354,1157353200"; d="scan'208"; a="150250765:sNHT24026345" Message-ID: <453EF96C.5030903@intel.com> Date: Wed, 25 Oct 2006 13:43:08 +0800 From: "bibo,mao" User-Agent: Thunderbird 1.5.0.7 (Windows/20060909) MIME-Version: 1.0 To: The development of GRUB 2 References: <453DBE9A.7040300@intel.com> <87fydd3ll4.fsf@night.trouble.net> <877iyp3j23.fsf@night.trouble.net> In-Reply-To: <877iyp3j23.fsf@night.trouble.net> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [PATCH 3/3] grub EFI disk device enumberating 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: Wed, 25 Oct 2006 05:43:14 -0000 Johan Rydberg wrote: > Johan Rydberg writes: > > > This code can be shorter; you only have to compare the lengths. If > > they match, you can do a memcmp on the whole device path. > > It could look something like this; > > /* Returns zero if device path SUBPATH is a subpath of device path > PATH. */ > static int > compare_subpath (const grub_efi_device_path_t *subpath, > const grub_efi_device_path_t *path) > { > if (! subpath || ! path) > return 1; > > while (1) > { > int len, ret; > > if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (subpath)) > return 0; > else if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (path)) > return 1; > > if (GRUB_EFI_DEVICE_PATH_LENGTH (subpath) > != GRUB_EFI_DEVICE_PATH_LENGTH (path)) > return ((int) GRUB_EFI_DEVICE_PATH_LENGTH (subpath) > - (int) GRUB_EFI_DEVICE_PATH_LENGTH (path)); > > len = GRUB_EFI_DEVICE_PATH_LENGTH (path); > ret = grub_memcmp (subpath, path, len); > if (ret) > return ret; > > path = (grub_efi_device_path_t *) ((char *) path + len); > subpath = (grub_efi_device_path_t *) ((char *) subpath + len); > } > } > > I guess that should work at least, it is not tested. I tested on my EFI IA32 bios, it works for me, your method is better than me, I incorporated your function in my second patch. thanks bibo,mao > > In gnufi I have a device_path_iterate function that could be used for > these kind of things. Maybe we should bring it in to GRUB2. > > /* Iterate nodes of the device path. *PATHP should be set to point to > the path that is to be iterated. NULL will be returned when the > end of the path has been reached. */ > efi_device_path_t * > efi_device_path_iterate (efi_device_path_t **pathp) > { > efi_device_path_t *p = *pathp; > > if (EFI_END_ENTIRE_DEVICE_PATH (p)) > return NULL; > else > { > efi_uint_t len = EFI_DEVICE_PATH_LENGTH (p); > *pathp = (efi_device_path_t *) (((char *) p) + len); > return p; > } > } > > ~j > > --- grub2.org/disk/efi/efidisk.c 2006-10-25 12:47:28.000000000 +0800 +++ grub2/disk/efi/efidisk.c 2006-10-25 12:50:19.000000000 +0800 @@ -87,6 +87,39 @@ find_last_device_path (const grub_efi_de return p; } +/* Returns zero if device path SUBPATH is a subpath of device path + PATH. */ +static int +compare_subpath (const grub_efi_device_path_t *subpath, + const grub_efi_device_path_t *path) +{ + if (! subpath || ! path) + return 1; + + while (1) + { + int len, ret; + + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (subpath)) + return 0; + else if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (path)) + return 1; + + if (GRUB_EFI_DEVICE_PATH_LENGTH (subpath) + != GRUB_EFI_DEVICE_PATH_LENGTH (path)) + return ((int) GRUB_EFI_DEVICE_PATH_LENGTH (subpath) + - (int) GRUB_EFI_DEVICE_PATH_LENGTH (path)); + + len = GRUB_EFI_DEVICE_PATH_LENGTH (path); + ret = grub_memcmp (subpath, path, len); + if (ret) + return ret; + + path = (grub_efi_device_path_t *) ((char *) path + len); + subpath = (grub_efi_device_path_t *) ((char *) subpath + len); + } +} + /* Compare device paths. */ static int compare_device_paths (const grub_efi_device_path_t *dp1, @@ -197,44 +230,6 @@ make_devices (void) return devices; } -/* Find the parent device. */ -static struct grub_efidisk_data * -find_parent_device (struct grub_efidisk_data *devices, - struct grub_efidisk_data *d) -{ - grub_efi_device_path_t *dp, *ldp; - struct grub_efidisk_data *parent; - - dp = duplicate_device_path (d->device_path); - if (! dp) - return 0; - - ldp = find_last_device_path (dp); - ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; - ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; - ldp->length[0] = sizeof (*ldp); - ldp->length[1] = 0; - - for (parent = devices; parent; parent = parent->next) - { - /* Ignore itself. */ - if (parent == d) - continue; - - if (compare_device_paths (parent->device_path, dp) == 0) - { - /* Found. */ - if (! parent->last_device_path) - parent = 0; - - break; - } - } - - grub_free (dp); - return parent; -} - static int iterate_child_devices (struct grub_efidisk_data *devices, struct grub_efidisk_data *d, @@ -305,63 +300,6 @@ static void name_devices (struct grub_efidisk_data *devices) { struct grub_efidisk_data *d; - - /* First, identify devices by media device paths. */ - for (d = devices; d; d = d->next) - { - grub_efi_device_path_t *dp; - - dp = d->last_device_path; - if (! dp) - continue; - - if (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE) - { - int is_hard_drive = 0; - - switch (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp)) - { - case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE: - is_hard_drive = 1; - /* Fall through by intention. */ - case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE: - { - struct grub_efidisk_data *parent; - - parent = find_parent_device (devices, d); - if (parent) - { - if (is_hard_drive) - { -#if 0 - grub_printf ("adding a hard drive by a partition: "); - grub_print_device_path (parent->device_path); -#endif - add_device (&hd_devices, parent); - } - else - { -#if 0 - grub_printf ("adding a cdrom by a partition: "); - grub_print_device_path (parent->device_path); -#endif - add_device (&cd_devices, parent); - } - - /* Mark the parent as used. */ - parent->last_device_path = 0; - } - } - /* Mark itself as used. */ - d->last_device_path = 0; - break; - - default: - /* For now, ignore the others. */ - break; - } - } - } /* Let's see what can be added more. */ for (d = devices; d; d = d->next) @@ -374,34 +312,22 @@ name_devices (struct grub_efidisk_data * continue; m = d->block_io->media; - if (m->logical_partition) - { - /* Only one partition in a non-media device. Assume that this - is a floppy drive. */ -#if 0 - grub_printf ("adding a floppy by guessing: "); - grub_print_device_path (d->device_path); -#endif - add_device (&fd_devices, d); - } - else if (m->read_only && m->block_size > GRUB_DISK_SECTOR_SIZE) + if (GRUB_EFI_DEVICE_PATH_TYPE(dp) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE) { - /* This check is too heuristic, but assume that this is a - CDROM drive. */ -#if 0 - grub_printf ("adding a cdrom by guessing: "); - grub_print_device_path (d->device_path); -#endif - add_device (&cd_devices, d); + if (m->read_only && m->block_size > GRUB_DISK_SECTOR_SIZE) + { + grub_printf("adding a cd by guessing\n"); + add_device (&cd_devices, d); + } else + { + grub_printf("adding a hd by guessing\n"); + add_device (&hd_devices, d); + } } - else + if (GRUB_EFI_DEVICE_PATH_TYPE(dp) == GRUB_EFI_ACPI_DEVICE_PATH_TYPE) { - /* The default is a hard drive. */ -#if 0 - grub_printf ("adding a hard drive by guessing: "); - grub_print_device_path (d->device_path); -#endif - add_device (&hd_devices, d); + grub_printf ("adding a floppy by guessing\n"); + add_device (&fd_devices, d); } } } @@ -734,7 +660,6 @@ grub_efidisk_get_device_name (grub_efi_h grub_disk_t parent = 0; char *partition_name = 0; char *device_name; - grub_efi_device_path_t *dup_dp, *dup_ldp; grub_efi_hard_drive_device_path_t hd; auto int find_parent_disk (const char *name); auto int find_partition (grub_disk_t disk, const grub_partition_t part); @@ -753,7 +678,7 @@ grub_efidisk_get_device_name (grub_efi_h struct grub_efidisk_data *d; d = disk->data; - if (compare_device_paths (d->device_path, dup_dp) == 0) + if (compare_subpath (d->device_path, dp) == 0) { parent = disk; return 1; @@ -778,20 +703,7 @@ grub_efidisk_get_device_name (grub_efi_h return 0; } - /* It is necessary to duplicate the device path so that GRUB - can overwrite it. */ - dup_dp = duplicate_device_path (dp); - if (! dup_dp) - return 0; - - dup_ldp = find_last_device_path (dup_dp); - dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; - dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; - dup_ldp->length[0] = sizeof (*dup_ldp); - dup_ldp->length[1] = 0; - grub_efidisk_iterate (find_parent_disk); - grub_free (dup_dp); if (! parent) return 0;