https://git.reactos.org/?p=reactos.git;a=commitdiff;h=21c51eed0517ccca05ccf…
commit 21c51eed0517ccca05ccf5a0724e0c9ce2a5e058
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Sun Sep 29 19:20:15 2019 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Mon Oct 7 02:54:07 2019 +0200
[FREELDR] Several changes regarding chainloading and Linux boot.
- Introduce "Relocator16Boot()". So far its aim is just to correctly set
the CPU state (segments, registers, flags) to what is expected by a
given boot image before running it.
This function can be seen as the embryonic state of a future boot relocator
(see e.g. GRUB or SYSLINUX) that would also relocate the boot image at
the correct places. (Such feature is needed when boot images have to
be loaded in memory areas that cover where the boot loader is in memory.)
- Implement ChainLoadBiosBootSectorCode() around it.
- Replace BootOldLinuxKernel() and BootNewLinuxKernel() by a new
BootLinuxKernel() function (in assembly) that relocates the kernel
to a given position and then boot it, using Relocator16Boot().
Ideally the relocation should be done by a future boot relocator...
Implementation notes for Relocator16Boot():
===========================================
For setting the CPU state the function is based on a similar code as the
Int386() helper, namely it takes a pointer to REGS structure and pass
this information through the 32->16 bits call before setting the CPU state
in accordance.
New stack segment/pointer and code segment/pointer are also specified.
For passing these values through the 32->16 bits call the 16-bit BSS
memory offsets "BSS_CallbackReturn" and "BSS_RealModeEntry"
(respectively)
are reused.
---
boot/freeldr/freeldr/arch/i386/entry.S | 74 ++++++++------
boot/freeldr/freeldr/arch/i386/i386rtl.c | 27 +++++
boot/freeldr/freeldr/arch/i386/linux.S | 125 +++++++++++++++++++----
boot/freeldr/freeldr/arch/powerpc/mach.c | 12 ++-
boot/freeldr/freeldr/arch/realmode/helpers.inc | 54 ++++++++--
boot/freeldr/freeldr/arch/realmode/i386.S | 9 +-
boot/freeldr/freeldr/arch/realmode/int386.inc | 4 -
boot/freeldr/freeldr/arch/realmode/linux.inc | 15 ---
boot/freeldr/freeldr/include/arch/pc/pcbios.h | 19 +++-
boot/freeldr/freeldr/include/arch/pc/x86common.h | 7 +-
boot/freeldr/freeldr/include/linux.h | 9 +-
boot/freeldr/freeldr/linuxboot.c | 33 ++++--
12 files changed, 281 insertions(+), 107 deletions(-)
diff --git a/boot/freeldr/freeldr/arch/i386/entry.S
b/boot/freeldr/freeldr/arch/i386/entry.S
index 4c95e64e605..9e7090f0f12 100644
--- a/boot/freeldr/freeldr/arch/i386/entry.S
+++ b/boot/freeldr/freeldr/arch/i386/entry.S
@@ -106,50 +106,58 @@ _Reboot:
/* Stop the floppy drive motor */
call _DiskStopFloppyMotor
- /* Set the function ID */
+ /* Set the function ID and switch to real mode (we don't return) */
mov bx, FNID_Reboot
-
- /* Switch to real mode (we don't return) */
jmp SwitchToReal
/*
- * VOID __cdecl ChainLoadBiosBootSectorCode(
- * IN UCHAR BootDrive OPTIONAL,
- * IN ULONG BootPartition OPTIONAL);
+ * VOID __cdecl Relocator16Boot(
+ * IN REGS* In,
+ * IN USHORT StackSegment,
+ * IN USHORT StackPointer,
+ * IN USHORT CodeSegment,
+ * IN USHORT CodePointer);
+ *
+ * RETURNS: Nothing.
*
- * RETURNS: Nothing
+ * NOTE: The implementation of this function is similar to that of Int386(),
+ * with the proviso that no attempt is done to save the original values of
+ * the registers since we will not need them anyway, as we do not return back
+ * to the caller but instead place the machine in a permanent new CPU state.
*/
-PUBLIC _ChainLoadBiosBootSectorCode
-_ChainLoadBiosBootSectorCode:
- /* Set the boot drive */
- mov dl, [esp + 4]
- test dl, dl
- jnz set_part
- mov dl, byte ptr ds:[_FrldrBootDrive]
-
- /* Set the boot partition */
-set_part:
- mov eax, [esp + 8]
- test eax, eax
- jnz continue
- mov eax, dword ptr ds:[_FrldrBootPartition]
-continue:
- /* Store the 1-byte truncated partition number in DH */
- mov dh, al
+PUBLIC _Relocator16Boot
+_Relocator16Boot:
+
+ /* Copy input registers */
+ mov esi, dword ptr [esp + 4]
+ mov edi, BSS_RegisterSet
+ mov ecx, REGS_SIZE / 4
+ rep movsd
+
+ /* Set the stack segment/offset */
+ // Since BSS_CallbackReturn contains a ULONG, store in its high word
+ // the stack segment and in its low word the stack offset.
+ mov ax, word ptr [esp + 8]
+ shl eax, 16
+ mov ax, word ptr [esp + 12]
+ mov dword ptr ds:[BSS_CallbackReturn], eax
/*
- * Don't stop the floppy drive motor when we are just booting a bootsector,
- * a drive, or a partition. If we were to stop the floppy motor, the BIOS
- * wouldn't be informed and if the next read is to a floppy then the BIOS
- * will still think the motor is on and this will result in a read error.
+ * Set the code segment/offset (Copy entry point)
+ * NOTE: We permanently *ERASE* the contents of ds:[BSS_RealModeEntry]
+ * but it is not a problem since we are going to place the machine in
+ * a permanent new CPU state.
*/
- // call _DiskStopFloppyMotor
-
- /* Set the function ID */
- mov bx, FNID_ChainLoadBiosBootSectorCode
+ // Since BSS_RealModeEntry contains a ULONG, store in its high word
+ // the code segment and in its low word the code offset.
+ mov ax, word ptr [esp + 16]
+ shl eax, 16
+ mov ax, word ptr [esp + 20]
+ mov dword ptr ds:[BSS_RealModeEntry], eax
- /* Switch to real mode (we don't return) */
+ /* Set the function ID and switch to real mode (we don't return) */
+ mov bx, FNID_Relocator16Boot
jmp SwitchToReal
diff --git a/boot/freeldr/freeldr/arch/i386/i386rtl.c
b/boot/freeldr/freeldr/arch/i386/i386rtl.c
index 90da33db91c..e4ef701da52 100644
--- a/boot/freeldr/freeldr/arch/i386/i386rtl.c
+++ b/boot/freeldr/freeldr/arch/i386/i386rtl.c
@@ -88,3 +88,30 @@ void sound(int freq)
WRITE_PORT_UCHAR((PUCHAR)0x42, scale >> 8);
WRITE_PORT_UCHAR((PUCHAR)0x61, READ_PORT_UCHAR((PUCHAR)0x61) | 3);
}
+
+VOID __cdecl ChainLoadBiosBootSectorCode(
+ IN UCHAR BootDrive OPTIONAL,
+ IN ULONG BootPartition OPTIONAL)
+{
+ REGS Regs;
+
+ RtlZeroMemory(&Regs, sizeof(Regs));
+
+ /* Set the boot drive and the boot partition */
+ Regs.b.dl = (UCHAR)(BootDrive ? BootDrive : FrldrBootDrive);
+ Regs.b.dh = (UCHAR)(BootPartition ? BootPartition : FrldrBootPartition);
+
+ /*
+ * Don't stop the floppy drive motor when we are just booting a bootsector,
+ * a drive, or a partition. If we were to stop the floppy motor, the BIOS
+ * wouldn't be informed and if the next read is to a floppy then the BIOS
+ * will still think the motor is on and this will result in a read error.
+ */
+ // DiskStopFloppyMotor();
+
+ Relocator16Boot(&Regs,
+ /* Stack segment:pointer */
+ 0x0000, 0x7C00,
+ /* Code segment:pointer */
+ 0x0000, 0x7C00);
+}
diff --git a/boot/freeldr/freeldr/arch/i386/linux.S
b/boot/freeldr/freeldr/arch/i386/linux.S
index d2b187cbf30..cc18346a17e 100644
--- a/boot/freeldr/freeldr/arch/i386/linux.S
+++ b/boot/freeldr/freeldr/arch/i386/linux.S
@@ -19,40 +19,121 @@
#include <asm.inc>
#include <arch/pc/x86common.h>
+#include <arch/pc/pcbios.h>
EXTERN _DiskStopFloppyMotor:PROC
-EXTERN i386CallRealMode:PROC
+EXTERN _Relocator16Boot:PROC
+EXTERN _FrldrBootDrive:BYTE
+EXTERN _FrldrBootPartition:DWORD
.code32
+Regs:
+ .space REGS_SIZE
+
/*
- * VOID BootOldLinuxKernel(ULONG KernelSize);
+ * VOID __cdecl BootLinuxKernel(
+ * IN ULONG KernelSize,
+ * IN PVOID KernelCurrentLoadAddress,
+ * IN PVOID KernelTargetLoadAddress,
+ * IN UCHAR DriveNumber,
+ * IN ULONG PartitionNumber);
*/
-PUBLIC _BootOldLinuxKernel
-_BootOldLinuxKernel:
-
- /* First we have to copy the kernel down from 0x100000 to 0x10000 */
- /* The reason we can overwrite low memory is because this code */
- /* executes between 0000:8000 and 0000:FFFF. That leaves space for */
- /* 32k of code before we start interfering with Linux kernel address space. */
-
- /* Get KernelSize in ECX and move the kernel down */
- mov ecx, [esp + 4]
- mov esi, HEX(100000)
- mov edi, HEX(10000)
- rep movsb
+PUBLIC _BootLinuxKernel
+_BootLinuxKernel:
- /* Fall through */
-
-PUBLIC _BootNewLinuxKernel
-_BootNewLinuxKernel:
/* Stop the floppy drive motor */
call _DiskStopFloppyMotor
- mov bx, FNID_BootLinuxKernel
- call i386CallRealMode
+ /* Set all segment registers to 0x9000 */
+ mov ax, HEX(9000)
+ mov word ptr [Regs + REGS_DS], ax
+ mov word ptr [Regs + REGS_ES], ax
+ mov word ptr [Regs + REGS_FS], ax
+ mov word ptr [Regs + REGS_GS], ax
+
+ /* Set the boot drive */
+ xor edx, edx
+ mov dl, byte ptr [esp + 16]
+ test dl, dl
+ jnz set_part
+ mov dl, byte ptr ds:[_FrldrBootDrive]
+
+ /* Set the boot partition */
+set_part:
+ mov eax, dword ptr [esp + 20]
+ test eax, eax
+ jnz continue
+ mov eax, dword ptr ds:[_FrldrBootPartition]
+continue:
+ /* Store the 1-byte truncated partition number in DH */
+ mov dh, al
+
+ mov dword ptr [Regs + REGS_EDX], edx
+
+ /*
+ * Relocate the kernel image to its final destination (can be as low as 0x10000).
+ * The reason we can overwrite low memory is because this code executes
+ * between 0000:8000 and 0000:FFFF. That leaves space for 32k of code
+ * before we start interfering with Linux kernel address space.
+ */
+
+ /* Get KernelSize in ECX */
+ mov ecx, dword ptr [esp + 4]
+ test ecx, ecx // If size is zero, do not perform relocations
+ jz after_reloc
+
+ /* Load the source and target addresses */
+ mov esi, dword ptr [esp + 8] // HEX(100000) // LINUX_KERNEL_LOAD_ADDRESS
+ mov edi, dword ptr [esp + 12] // HEX(10000)
+
+//
+// FIXME: Support relocating *upwards*, overlapping regions, aligned addresses,
+// etc... !! See memmove code.
+//
+ /* Check how we should perform relocation */
+ cmp edi, esi
+ je after_reloc // target == source: do not perform relocations
+ ja reloc_up // target > source: relocate up
+// jb reloc_down // target < source: relocate down (default)
+
+reloc_down:
+ /* Move the kernel down - Start with low addresses and increment them */
+ cld
+#if 0
+ rep movsb
+#else
+ mov edx, ecx // Copy the total number of bytes in EDX
+ and edx, HEX(0FFFFFFFC) // Number of bytes we copy using DWORDs
+ xor edx, ecx // Number of remaining bytes to copy after the DWORDs
+ shr ecx, 2 // Count number of DWORDs
+ rep movsd // Move DWORDs
+ mov ecx, edx // Count number of remaining bytes
+ rep movsb // Move bytes
+#endif
+ jmp after_reloc
+
+reloc_up:
+ /* Move the kernel up - Start with high addresses and decrement them */
+ std
+ add esi, ecx
+ add edi, ecx
+ dec esi
+ dec edi
+ rep movsb
+ // jmp after_reloc
+
+after_reloc:
+
+ push HEX(0000) // CodePointer
+ push HEX(9020) // CodeSegment
+ push HEX(9000) // StackPointer
+ push HEX(9000) // StackSegment
+ mov eax, offset Regs
+ push eax
+ call _Relocator16Boot
- /* We should never get here */
+ /* We must never get there */
int 3
END
diff --git a/boot/freeldr/freeldr/arch/powerpc/mach.c
b/boot/freeldr/freeldr/arch/powerpc/mach.c
index 840cbfa5657..e5a93d9403d 100644
--- a/boot/freeldr/freeldr/arch/powerpc/mach.c
+++ b/boot/freeldr/freeldr/arch/powerpc/mach.c
@@ -533,11 +533,13 @@ void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value) {
SetPhysByte(((ULONG)Address)+0x80000000, Value);
}
-void BootOldLinuxKernel( unsigned long size ) {
- ofw_exit();
-}
-
-void BootNewLinuxKernel() {
+VOID __cdecl BootLinuxKernel(
+ IN ULONG KernelSize,
+ IN PVOID KernelCurrentLoadAddress,
+ IN PVOID KernelTargetLoadAddress,
+ IN UCHAR DriveNumber,
+ IN ULONG PartitionNumber)
+{
ofw_exit();
}
diff --git a/boot/freeldr/freeldr/arch/realmode/helpers.inc
b/boot/freeldr/freeldr/arch/realmode/helpers.inc
index 9fbe7366ebc..922cb8dfbd6 100644
--- a/boot/freeldr/freeldr/arch/realmode/helpers.inc
+++ b/boot/freeldr/freeldr/arch/realmode/helpers.inc
@@ -128,7 +128,7 @@ Reboot:
ljmp16 HEX(0F000), HEX(0FFF0)
-ChainLoadBiosBootSectorCode:
+Relocator16Boot:
cli
/* Disable A20 address line */
@@ -138,14 +138,54 @@ ChainLoadBiosBootSectorCode:
mov ax, HEX(0003)
int HEX(10)
- /* Load segment registers */
- xor ax, ax
+ /* Get current EFLAGS and mask CF, ZF and SF */
+ pushf
+ pop cx
+ and cx, not (EFLAGS_CF or EFLAGS_ZF or EFLAGS_SF)
+
+ /* Get flags CF, ZF and SF from the REGS structure */
+ mov ax, word ptr cs:[BSS_RegisterSet + REGS_EFLAGS]
+ and ax, (EFLAGS_CF or EFLAGS_ZF or EFLAGS_SF)
+
+ /* Combine flags and set them */
+ or ax, cx
+ push ax
+ popf
+
+ /* Setup the segment registers */
+ mov ax, word ptr cs:[BSS_RegisterSet + REGS_DS]
mov ds, ax
+ mov ax, word ptr cs:[BSS_RegisterSet + REGS_ES]
mov es, ax
+ mov ax, word ptr cs:[BSS_RegisterSet + REGS_FS]
mov fs, ax
+ mov ax, word ptr cs:[BSS_RegisterSet + REGS_GS]
mov gs, ax
- mov ss, ax
- mov esp, HEX(7C00)
- /* Jump to the bootsector code */
- ljmp16 HEX(0000), HEX(7C00)
+ /* Patch the jump address (segment:offset) */
+ mov eax, dword ptr cs:[BSS_RealModeEntry]
+ mov dword ptr cs:[Relocator16Address], eax
+
+ /* Switch the stack (segment:offset) */
+ mov eax, dword ptr cs:[BSS_CallbackReturn]
+ shr eax, 16
+ mov ss, ax
+ mov eax, dword ptr cs:[BSS_CallbackReturn]
+ and eax, HEX(0FFFF)
+ mov esp, eax
+
+ /* Setup the registers */
+ mov eax, dword ptr cs:[BSS_RegisterSet + REGS_EAX]
+ mov ebx, dword ptr cs:[BSS_RegisterSet + REGS_EBX]
+ mov ecx, dword ptr cs:[BSS_RegisterSet + REGS_ECX]
+ mov edx, dword ptr cs:[BSS_RegisterSet + REGS_EDX]
+ mov esi, dword ptr cs:[BSS_RegisterSet + REGS_ESI]
+ mov edi, dword ptr cs:[BSS_RegisterSet + REGS_EDI]
+ // Don't setup ebp, we only use it as output! <-- FIXME!
+
+ /* Jump to the new CS:IP (e.g. jump to bootsector code...) */
+ .byte HEX(0EA) // ljmp16 segment:offset
+Relocator16Address:
+ .word HEX(7C00) // Default offset
+ .word HEX(0000) // Default segment
+ nop
diff --git a/boot/freeldr/freeldr/arch/realmode/i386.S
b/boot/freeldr/freeldr/arch/realmode/i386.S
index aaa261fdb70..f76a38ae464 100644
--- a/boot/freeldr/freeldr/arch/realmode/i386.S
+++ b/boot/freeldr/freeldr/arch/realmode/i386.S
@@ -8,7 +8,7 @@
.code16
-/* fat helper code */
+/* FAT helper code */
#include "fathelp.inc"
.org 512
@@ -143,11 +143,10 @@ pm_entrypoint:
CallbackTable:
.word Int386
.word Reboot
- .word ChainLoadBiosBootSectorCode
+ .word Relocator16Boot
.word PxeCallApi
.word PnpBiosGetDeviceNodeCount
.word PnpBiosGetDeviceNode
- .word BootLinuxKernel
/* 16-bit stack pointer */
@@ -194,16 +193,16 @@ gdtptr:
/* Real-mode IDT pointer */
rmode_idtptr:
- .word HEX(3ff) /* Limit */
+ .word HEX(3FF) /* Limit */
.long 0 /* Base Address */
#include "int386.inc"
#include "helpers.inc"
#include "pxe.inc"
#include "pnp.inc"
-#include "linux.inc"
.org (FREELDR_PE_BASE - FREELDR_BASE - 1)
.byte 0
.endcode16
+
END
diff --git a/boot/freeldr/freeldr/arch/realmode/int386.inc
b/boot/freeldr/freeldr/arch/realmode/int386.inc
index f8ab7039c96..49a63eb9e37 100644
--- a/boot/freeldr/freeldr/arch/realmode/int386.inc
+++ b/boot/freeldr/freeldr/arch/realmode/int386.inc
@@ -1,10 +1,6 @@
#include "../../include/arch/pc/pcbios.h"
-#define EFLAGS_CF HEX(01)
-#define EFLAGS_ZF HEX(40)
-#define EFLAGS_SF HEX(80)
-
Int386:
/* Save all registers + segment registers */
push ds
diff --git a/boot/freeldr/freeldr/arch/realmode/linux.inc
b/boot/freeldr/freeldr/arch/realmode/linux.inc
deleted file mode 100644
index 8b0312fac0d..00000000000
--- a/boot/freeldr/freeldr/arch/realmode/linux.inc
+++ /dev/null
@@ -1,15 +0,0 @@
-
-BootLinuxKernel:
- // dl must be set to the boot drive
-
- /* Load segment registers */
- cli
- mov bx, HEX(9000)
- mov ds, bx
- mov es, bx
- mov fs, bx
- mov gs, bx
- mov ss, bx
- mov sp, HEX(9000)
-
- ljmp16 HEX(9020), HEX(0000)
diff --git a/boot/freeldr/freeldr/include/arch/pc/pcbios.h
b/boot/freeldr/freeldr/include/arch/pc/pcbios.h
index 82fbe4e9670..804932de9ea 100644
--- a/boot/freeldr/freeldr/include/arch/pc/pcbios.h
+++ b/boot/freeldr/freeldr/include/arch/pc/pcbios.h
@@ -1,6 +1,12 @@
#ifndef _PCBIOS_H_
#define _PCBIOS_H_
+#ifdef __ASM__
+#define EFLAGS_CF HEX(01)
+#define EFLAGS_ZF HEX(40)
+#define EFLAGS_SF HEX(80)
+#endif
+
#ifndef __ASM__
#define MAX_BIOS_DESCRIPTORS 80
@@ -160,12 +166,19 @@ int __cdecl Int386(int ivec, REGS* in, REGS* out);
// If CF is set then the call failed (usually)
#define INT386_SUCCESS(regs) ((regs.x.eflags & EFLAGS_CF) == 0)
-VOID __cdecl ChainLoadBiosBootSectorCode( // Implemented in boot.S
+VOID __cdecl ChainLoadBiosBootSectorCode(
IN UCHAR BootDrive OPTIONAL,
IN ULONG BootPartition OPTIONAL);
-VOID __cdecl Reboot(VOID); // Implemented in boot.S
-VOID DetectHardware(VOID); // Implemented in hardware.c
+VOID __cdecl Relocator16Boot(
+ IN REGS* In,
+ IN USHORT StackSegment,
+ IN USHORT StackPointer,
+ IN USHORT CodeSegment,
+ IN USHORT CodePointer);
+
+VOID __cdecl Reboot(VOID);
+VOID DetectHardware(VOID);
#endif /* ! __ASM__ */
diff --git a/boot/freeldr/freeldr/include/arch/pc/x86common.h
b/boot/freeldr/freeldr/include/arch/pc/x86common.h
index 1b40ca39058..e4c304bb38c 100644
--- a/boot/freeldr/freeldr/include/arch/pc/x86common.h
+++ b/boot/freeldr/freeldr/include/arch/pc/x86common.h
@@ -54,11 +54,10 @@
/* Realmode function IDs */
#define FNID_Int386 0
#define FNID_Reboot 1
-#define FNID_ChainLoadBiosBootSectorCode 2
+#define FNID_Relocator16Boot 2
#define FNID_PxeCallApi 3
-#define FNID_PnpBiosGetDeviceNodeCount 4
-#define FNID_PnpBiosGetDeviceNode 5
-#define FNID_BootLinuxKernel 6
+#define FNID_PnpBiosGetDeviceNodeCount 4
+#define FNID_PnpBiosGetDeviceNode 5
/* Flag Masks */
#define CR0_PE_SET HEX(00000001) /* OR this value with CR0 to enable pmode */
diff --git a/boot/freeldr/freeldr/include/linux.h b/boot/freeldr/freeldr/include/linux.h
index d0b35105f2b..c51f70dab9f 100644
--- a/boot/freeldr/freeldr/include/linux.h
+++ b/boot/freeldr/freeldr/include/linux.h
@@ -128,8 +128,13 @@ typedef struct
} LINUX_SETUPSECTOR, *PLINUX_SETUPSECTOR;
#include <poppack.h>
-VOID __cdecl BootNewLinuxKernel(VOID); // Implemented in linux.S
-VOID __cdecl BootOldLinuxKernel(ULONG KernelSize); // Implemented in linux.S
+// Implemented in linux.S
+VOID __cdecl BootLinuxKernel(
+ IN ULONG KernelSize,
+ IN PVOID KernelCurrentLoadAddress,
+ IN PVOID KernelTargetLoadAddress,
+ IN UCHAR DriveNumber,
+ IN ULONG PartitionNumber);
ARC_STATUS
LoadAndBootLinux(
diff --git a/boot/freeldr/freeldr/linuxboot.c b/boot/freeldr/freeldr/linuxboot.c
index 48ebf53f54c..fa9ad60d442 100644
--- a/boot/freeldr/freeldr/linuxboot.c
+++ b/boot/freeldr/freeldr/linuxboot.c
@@ -154,6 +154,17 @@ LoadAndBootLinux(
}
}
+ /* If we haven't retrieved the BIOS drive and partition numbers above, do it now
*/
+ if (PartitionNumber == 0)
+ {
+ /* Retrieve the BIOS drive and partition numbers */
+ if (!DissectArcPath(BootPath, NULL, &DriveNumber, &PartitionNumber))
+ {
+ /* This is not a fatal failure, but just an inconvenience: display a message
*/
+ TRACE("DissectArcPath(%s) failed to retrieve BIOS drive and partition
numbers.\n", BootPath);
+ }
+ }
+
/* Get the kernel name */
LinuxKernelName = GetArgumentValue(Argc, Argv, "Kernel");
if (!LinuxKernelName || !*LinuxKernelName)
@@ -259,11 +270,13 @@ LoadAndBootLinux(
UiUnInitialize("Booting Linux...");
IniCleanup();
- if (LinuxSetupSector->LoadFlags & LINUX_FLAG_LOAD_HIGH)
- BootNewLinuxKernel();
- else
- BootOldLinuxKernel(LinuxKernelSize);
-
+ BootLinuxKernel(LinuxKernelSize, LinuxKernelLoadAddress,
+ (LinuxSetupSector->LoadFlags & LINUX_FLAG_LOAD_HIGH)
+ ? (PVOID)LINUX_KERNEL_LOAD_ADDRESS /* == 0x100000 */
+ : (PVOID)0x10000,
+ DriveNumber, PartitionNumber);
+ /* Must not return! */
+ return ESUCCESS;
LinuxBootFailed:
@@ -407,11 +420,17 @@ static BOOLEAN LinuxReadKernel(ULONG LinuxKernelFile)
RtlStringCbPrintfA(StatusText, sizeof(StatusText), "Loading %s",
LinuxKernelName);
UiDrawStatusText(StatusText);
- /* Allocate memory for Linux kernel */
+ /* Try to allocate memory for the Linux kernel; if it fails, allocate somewhere else
*/
LinuxKernelLoadAddress = MmAllocateMemoryAtAddress(LinuxKernelSize,
(PVOID)LINUX_KERNEL_LOAD_ADDRESS, LoaderSystemCode);
if (LinuxKernelLoadAddress != (PVOID)LINUX_KERNEL_LOAD_ADDRESS)
{
- return FALSE;
+ /* It's OK, let's allocate again somewhere else */
+ LinuxKernelLoadAddress = MmAllocateMemoryWithType(LinuxKernelSize,
LoaderSystemCode);
+ if (LinuxKernelLoadAddress == NULL)
+ {
+ TRACE("Failed to allocate 0x%lx bytes for the kernel image.\n",
LinuxKernelSize);
+ return FALSE;
+ }
}
LoadAddress = LinuxKernelLoadAddress;