2009/5/31 Javier Martín <lordhab...@gmail.com>:
> El sáb, 30-05-2009 a las 17:28 +0200, Vladimir 'phcoder' Serbinenko
> escribió:
>> >> > I'm fine with the change from "const void" to "const char", but we need
>> >> > to remove a preceding comment about void labels.
>> >> It's not that I'm opposed to void in principle. Just using the same
>> >> constructions to do the same things in different files makes code
>> >> easier to learn and port
>> >
>> > I wonder if we can go the other way and use void for all labels without
>> > storage.  Indeed, it's too easy to misuse a char variable by forgetting
>> > the ampersand before it.
>> Not  char []
> What if someone sees the code and thinks it's truly a char array? I
> insist: you are stirring a tempest in a teapot.
You're right. It turns into discussion about apple and oranges. Let's
forget this part
> Put it that way, I agree with your change. To the scrapper with
> parse_biosdisk then!
Sorry, I didn't mean to upset you. Here is a patch to do it
> I think the new behaviour
It's not a new behaviour on valid inputs since biosdisk does exactly
the same transformation.
> should be mentioned in
> the drivemap --help command, though I'm too tangled up with finals to be
> of any utility right now.
Good luck with your exams

Doing some tests I discovered that freedos MBR (but not the
bootsector) relies on %dl being preserved across int 0x13. In the
patch you can see additional hassle to preserve %dx.
Another problem I discovered is that %dl (chainloader) and bootdrive
(multiboot) passed to payload is out of sync.
Does anyone has a suggestion how to do it cleanly. The problems are:
-chainloader/multiboot shouldn't depend on biosdisk if possible
-%dl should be set accordingly to mapping
-%dl should be correct even if grub2 uses its own drivers (now it's
set to nonsense)
I have some ideas on this subject but would like to hear what others think.

-- 
Regards
Vladimir 'phcoder' Serbinenko
diff --git a/commands/i386/pc/drivemap.c b/commands/i386/pc/drivemap.c
index 98f4378..898fb51 100644
--- a/commands/i386/pc/drivemap.c
+++ b/commands/i386/pc/drivemap.c
@@ -143,62 +143,6 @@ drivemap_remove (grub_uint8_t newdrive)
     }
 }
 
-/* Given a device name, resolves its BIOS disk number and stores it in the
-   passed location, which should only be trusted if ERR_NONE is returned.  */
-static grub_err_t
-parse_biosdisk (const char *name, grub_uint8_t *disknum)
-{
-  grub_disk_t disk;
-  /* Skip the first ( in (hd0) - disk_open wants just the name.  */
-  if (*name == '(')
-    name++;
-
-  disk = grub_disk_open (name);
-  if (! disk)
-    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown device \"%s\"",
-		       name);
-  const enum grub_disk_dev_id id = disk->dev->id;
-  /* The following assignment is only sound if the device is indeed a
-     biosdisk.  The caller must check the return value.  */
-  if (disknum)
-    *disknum = disk->id;
-  grub_disk_close (disk);
-  if (id != GRUB_DISK_DEVICE_BIOSDISK_ID)
-    return grub_error (GRUB_ERR_BAD_DEVICE, "%s is not a BIOS disk", name);
-  return GRUB_ERR_NONE;
-}
-
-/* Given a BIOS disk number, returns its GRUB device name if it exists.
-   If the call succeeds, the resulting device string must be freed.
-   For nonexisting BIOS disk numbers, this function returns
-   GRUB_ERR_UNKNOWN_DEVICE.  */
-static grub_err_t
-revparse_biosdisk (const grub_uint8_t dnum, const char **output)
-{
-  int found = 0;
-  auto int find (const char *name);
-  int find (const char *name)
-  {
-    const grub_disk_t disk = grub_disk_open (name);
-    if (! disk)
-      return 0;
-    if (disk->id == dnum && disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID)
-      {
-	found = 1;
-	if (output)
-	  *output = grub_strdup (name);
-      }
-    grub_disk_close (disk);
-    return found;
-  }
-
-  grub_disk_dev_iterate (find);
-  if (found)
-    return GRUB_ERR_NONE;
-  return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "BIOS disk %02x not found",
-		     dnum);
-}
-
 /* Given a GRUB-like device name and a convenient location, stores the
    related BIOS disk number.  Accepts devices like \((f|h)dN\), with
    0 <= N < 128.  */
@@ -238,15 +182,13 @@ list_mappings (void)
   drivemap_node_t *curnode = map_head;
   while (curnode)
     {
-      const char *dname = 0;
-      grub_err_t err = revparse_biosdisk (curnode->redirto, &dname);
-      if (err != GRUB_ERR_NONE)
-	return err;
-      grub_printf ("%cD #%-3u (0x%02x)       %s\n",
+      grub_printf ("%cD #%-3u (0x%02x)       %cd%d\n",
 		   (curnode->newdrive & 0x80) ? 'H' : 'F',
-		   curnode->newdrive & 0x7F, curnode->newdrive, dname);
+		   curnode->newdrive & 0x7F, curnode->newdrive, 
+		   (curnode->redirto & 0x80) ? 'h' : 'f',
+		   curnode->redirto & 0x7F
+		   );
       curnode = curnode->next;
-      grub_free ((char *) dname);
     }
   return GRUB_ERR_NONE;
 }
@@ -286,17 +228,11 @@ grub_cmd_drivemap (struct grub_extcmd *cmd, int argc, char **args)
   if (argc != 2)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments required");
 
-  err = parse_biosdisk (args[0], &mapfrom);
+  err = tryparse_diskstring (args[0], &mapfrom);
   if (err != GRUB_ERR_NONE)
     return err;
 
-  /* When swapping we require both devices to be BIOS disks, but when
-     performing direct mappings we only require the 2nd argument to look
-     like a BIOS disk in order to resolve it into a BIOS disk number.  */
-  if (cmd->state[OPTIDX_SWAP].set)
-    err = parse_biosdisk (args[1], &mapto);
-  else
-    err = tryparse_diskstring (args[1], &mapto);
+  err = tryparse_diskstring (args[1], &mapto);
   if (err != GRUB_ERR_NONE)
     return err;
 
diff --git a/commands/i386/pc/drivemap_int13h.S b/commands/i386/pc/drivemap_int13h.S
index 23b7302..328459a 100644
--- a/commands/i386/pc/drivemap_int13h.S
+++ b/commands/i386/pc/drivemap_int13h.S
@@ -27,6 +27,11 @@
 
 /* The replacement int13 handler.   Preserve all registers.  */
 FUNCTION(grub_drivemap_handler)
+	/* Save %dx for future restore. */
+	push 	%dx
+	/* Push flags. Used to simulate interrupt with original flags. */
+	pushf
+
 	/* Map the drive number (always in DL).  */
 	push	%ax
 	push	%bx
@@ -46,16 +51,19 @@ not_found:
 	pop	%bx
 	pop	%ax
 
-	/* Upon arrival to this point the stack must be exactly like at entry.
-	   This long jump will transfer the caller's stack to the old INT13
-	   handler, thus making it return directly to the original caller.  */
-	.byte	0xea
+	/* lcall  */
+	.byte	0x9a
 
 /* Far pointer to the old handler.  Stored as a CS:IP in the style of real-mode
    IVT entries (thus PI:SC in mem).  */
 VARIABLE(grub_drivemap_oldhandler)
 	.word 0x0, 0x0
 
+	/* Restore %dx. */
+	pop %dx
+	iret
+	
+
 /* This label MUST be at the end of the copied block, since the installer code
    reserves additional space for mappings at runtime and copies them over it.  */
 .align 2
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to