Hi,

This patch implements a loader for NTLDR boot semantics (which are
the same in BootMGR, hence both are supported).

It still needs some cleanup in chainloader.c before it can be merged [1],
but I submit it so that others can test it and report if it works for
them.

[1] ideally, we should be able to share most code with the chainloader

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."
Index: kern/i386/pc/startup.S
===================================================================
--- kern/i386/pc/startup.S	(revision 2465)
+++ kern/i386/pc/startup.S	(working copy)
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008 Free Software Foundation, Inc.
+ *  Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
  *
  *  GRUB is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -576,6 +576,35 @@
 	ljmp	$0, $GRUB_MEMORY_MACHINE_BOOT_LOADER_ADDR
 	.code32
 
+/*
+ *  void grub_ntldr_real_boot (grub_uint8_t *boot_file, int drive, grub_uint32_t boot_file_size)
+ *
+ *  This starts NTLDR.
+ *
+ *  Register allocations for parameters:
+ *  %eax		*boot_file
+ *  %edx		drive
+ *  %ecx		boot_file_size
+ */
+
+ntldr_tmp_stack:
+	.long	0
+FUNCTION(grub_ntldr_real_boot)
+	/* Copy NTLDR from heap to its link address.  */
+	movl	%eax, %esi
+	movl	$GRUB_MEMORY_MACHINE_NTLDR_ADDR, %edi
+	cld
+	rep
+	movsb
+
+	/* Relocation may have taken over our stack, so use this one to
+	   hold our return address.  */
+	movl	$(ntldr_tmp_stack + 4), %esp
+	call	prot_to_real
+	.code16
+	ljmp	$(GRUB_MEMORY_MACHINE_NTLDR_ADDR >> 4), $0x0
+	.code32
+
 #include "../loader.S"
 
 /*
Index: include/grub/i386/pc/console.h
===================================================================
--- include/grub/i386/pc/console.h	(revision 2465)
+++ include/grub/i386/pc/console.h	(working copy)
@@ -51,7 +51,7 @@
 void grub_console_init (void);
 
 /* Finish the console system.  */
-void grub_console_fini (void);
+void EXPORT_FUNC(grub_console_fini) (void);
 
 #endif
 
Index: include/grub/i386/pc/loader.h
===================================================================
--- include/grub/i386/pc/loader.h	(revision 2465)
+++ include/grub/i386/pc/loader.h	(working copy)
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2002,2003,2004,2007  Free Software Foundation, Inc.
+ *  Copyright (C) 2002,2003,2004,2007,2009  Free Software Foundation, Inc.
  *
  *  GRUB is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -25,4 +25,7 @@
 /* This is an asm part of the chainloader.  */
 void EXPORT_FUNC(grub_chainloader_real_boot) (int drive, void *part_addr) __attribute__ ((noreturn));
 
+void EXPORT_FUNC(grub_ntldr_real_boot) (grub_uint8_t *boot_file, int drive,
+					grub_uint32_t boot_file_size) __attribute__ ((noreturn));
+
 #endif /* ! GRUB_LOADER_MACHINE_HEADER */
Index: include/grub/i386/pc/memory.h
===================================================================
--- include/grub/i386/pc/memory.h	(revision 2465)
+++ include/grub/i386/pc/memory.h	(working copy)
@@ -1,7 +1,7 @@
 /* memory.h - describe the memory map */
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2002,2007,2008  Free Software Foundation, Inc.
+ *  Copyright (C) 2002,2007,2008,2009  Free Software Foundation, Inc.
  *
  *  GRUB is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -63,6 +63,9 @@
 /* The address where another boot loader is loaded.  */
 #define GRUB_MEMORY_MACHINE_BOOT_LOADER_ADDR	0x7c00
 
+/* The address where NTLDR is loaded.  */
+#define GRUB_MEMORY_MACHINE_NTLDR_ADDR		0x20000
+
 /* The flag for protected mode.  */
 #define GRUB_MEMORY_MACHINE_CR0_PE_ON		0x1
 
Index: loader/i386/pc/chainloader.c
===================================================================
--- loader/i386/pc/chainloader.c	(revision 2465)
+++ loader/i386/pc/chainloader.c	(working copy)
@@ -1,7 +1,7 @@
 /* chainloader.c - boot another boot loader */
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2002,2004,2007  Free Software Foundation, Inc.
+ *  Copyright (C) 2002,2004,2007,2009  Free Software Foundation, Inc.
  *
  *  GRUB is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -20,6 +20,7 @@
 #include <grub/loader.h>
 #include <grub/machine/loader.h>
 #include <grub/machine/chainloader.h>
+#include <grub/machine/console.h>
 #include <grub/file.h>
 #include <grub/err.h>
 #include <grub/device.h>
@@ -36,12 +37,17 @@
 static grub_dl_t my_mod;
 static int boot_drive;
 static void *boot_part_addr;
+static grub_uint8_t *boot_file;
+static grub_off_t boot_file_size;
 
 static grub_err_t
 grub_chainloader_boot (void)
 {
-  grub_chainloader_real_boot (boot_drive, boot_part_addr);
+  /* NTLDR expects console in text mode.  */
+  grub_console_fini ();
 
+  grub_ntldr_real_boot (boot_file, boot_drive, (grub_uint32_t) boot_file_size);
+
   /* Never reach here.  */
   return GRUB_ERR_NONE;
 }
@@ -68,24 +74,11 @@
   if (! file)
     goto fail;
 
-  /* Read the first block.  */
-  if (grub_file_read (file, (void *) 0x7C00, GRUB_DISK_SECTOR_SIZE)
-      != GRUB_DISK_SECTOR_SIZE)
-    {
-      if (grub_errno == GRUB_ERR_NONE)
-	grub_error (GRUB_ERR_BAD_OS, "too small");
+  boot_file_size = file->size;
 
-      goto fail;
-    }
+  boot_file = grub_malloc (boot_file_size);
 
-  /* Check the signature.  */
-  signature = *((grub_uint16_t *) (0x7C00 + GRUB_DISK_SECTOR_SIZE - 2));
-  if (signature != grub_le_to_cpu16 (0xaa55)
-      && ! (flags & GRUB_CHAINLOADER_FORCE))
-    {
-      grub_error (GRUB_ERR_BAD_OS, "invalid signature");
-      goto fail;
-    }
+  grub_file_read (file, boot_file, boot_file_size);
 
   grub_file_close (file);
 
@@ -95,11 +88,26 @@
   if (dev && dev->disk && dev->disk->partition)
     {
       grub_disk_read (dev->disk, dev->disk->partition->offset, 446, 64,
-		      (void *) GRUB_MEMORY_MACHINE_PART_TABLE_ADDR);
+		      GRUB_MEMORY_MACHINE_PART_TABLE_ADDR);
       part_addr = (void *) (GRUB_MEMORY_MACHINE_PART_TABLE_ADDR
 			    + (dev->disk->partition->index << 4));
     }
 
+  if (! dev)
+    grub_fatal ("boo");
+
+  /* Read the first block.  */
+  grub_disk_read (dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, (void *) 0x7C00);
+
+  /* Check the signature.  */
+  signature = *((grub_uint16_t *) (0x7C00 + GRUB_DISK_SECTOR_SIZE - 2));
+  if (signature != grub_le_to_cpu16 (0xaa55)
+      && ! (flags & GRUB_CHAINLOADER_FORCE))
+    {
+      grub_error (GRUB_ERR_BAD_OS, "invalid signature");
+      goto fail;
+    }
+
   if (dev)
     grub_device_close (dev);
   
@@ -109,7 +117,7 @@
   boot_drive = drive;
   boot_part_addr = part_addr;
 
-  grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 1);
+  grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
   return;
 
  fail:
@@ -145,8 +153,8 @@
 
 GRUB_MOD_INIT(chainloader)
 {
-  cmd = grub_register_command ("chainloader", grub_cmd_chainloader,
-			       0, "load another boot loader");
+  cmd = grub_register_command ("ntldr", grub_cmd_chainloader,
+			       0, "load NTLDR");
   my_mod = mod;
 }
 
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to