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 #include #include +#include #include #include #include @@ -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; }