https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3377b901b2604863527fd…
commit 3377b901b2604863527fdff291eb133d7ded4a1f
Author: Carlo Bramini <30959007+carlo-bramini(a)users.noreply.github.com>
AuthorDate: Tue Oct 8 16:52:30 2019 +0200
Commit: Hermès BÉLUSCA - MAÏTO <hermes.belusca-maito(a)reactos.org>
CommitDate: Tue Oct 8 16:52:30 2019 +0200
[CMDUTILS] Add italian translation for 'comp' utility. (#1931)
---
base/applications/cmdutils/comp/comp.rc | 3 +++
base/applications/cmdutils/comp/lang/it-IT.rc | 23 +++++++++++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/base/applications/cmdutils/comp/comp.rc b/base/applications/cmdutils/comp/comp.rc
index d440990dee7..9e564212ef9 100644
--- a/base/applications/cmdutils/comp/comp.rc
+++ b/base/applications/cmdutils/comp/comp.rc
@@ -21,6 +21,9 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#ifdef LANGUAGE_FR_FR
#include "lang/fr-FR.rc"
#endif
+#ifdef LANGUAGE_IT_IT
+ #include "lang/it-IT.rc"
+#endif
#ifdef LANGUAGE_PL_PL
#include "lang/pl-PL.rc"
#endif
diff --git a/base/applications/cmdutils/comp/lang/it-IT.rc b/base/applications/cmdutils/comp/lang/it-IT.rc
new file mode 100644
index 00000000000..c7cd95ffb51
--- /dev/null
+++ b/base/applications/cmdutils/comp/lang/it-IT.rc
@@ -0,0 +1,23 @@
+LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL
+
+STRINGTABLE
+BEGIN
+ IDS_HELP "Confronta il contenuto di due file o gruppi di file.\n\n\
+COMP [/L] [/A] [file1] [file2]\n\n\
+ file1 Specifica la posizione ed il nome del primo file da confrontare.\n\
+ file2 Specifica la posizione ed il nome del secondo file da confrontare.\n\
+ /A Visualizza le differenze con caratteri ASCII (predefinito: esadecimale).\n\
+ /L Visualizza i numeri delle linee differenti.\n"
+ IDS_INVALIDSWITCH "Parametro non valido - /%c\n"
+ IDS_BADSYNTAX "Errore di sintassi sulla linea di comando\n"
+ IDS_FILEERROR "Impossibile aprire/trovare il file: %s\n"
+ IDS_COMPARING "Confronto %s con %s...\n"
+ IDS_FILESIZEERROR "Impossibile determinare la dimensione del file: %s\n"
+ IDS_SIZEDIFFERS "I file hanno dimensione differente.\n"
+ IDS_READERROR "Errore di lettura dei file.\n"
+ IDS_MISMATCHLINE "Errore di confronto alla LINEA %d\n"
+ IDS_MISMATCHOFFSET "Errore di confronto all'OFFSET 0x%X\n"
+ IDS_ASCIIDIFF "file%d = %c\n"
+ IDS_HEXADECIMALDIFF "file%d = %X\n"
+ IDS_MATCH "Confronto dei file OK\n"
+END
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0d6631c2da3eb593623af…
commit 0d6631c2da3eb593623af9cff8fef86530aecd55
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Wed Oct 2 03:20:10 2019 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Tue Oct 8 01:30:15 2019 +0200
[FREELDR] Fix an inconsistency bug when switching the CPU state back to 16-bit real mode.
Basically it appeared that without this fix, the CPU was somehow residing
in an inconsistent state, that made it crash when a full 16-bit real-mode
to 32-bit protected mode transition occurred. (Encountered when trying
to load Linux, see problem description below.)
In that situation, Bochs reports that the CPU is in "compatibility mode".
The fix is based from information from Fig.1-6 "Operating Modes of the
AMD64 Architecture" (page 12) and Chapter 14 (pages 429-446) of the
"AMD64 Architecture Programmer’s Manual Volume 2: System Programming"
https://www.amd.com/system/files/TechDocs/24593.pdf
*** THE PROBLEM ***
When booting Linux using x86 FreeLdr everything goes well.
When trying to do the same using x64 FreeLdr, the Linux code (both the
boot sector, the setup sector and the main kernel contents) is all
correctly loaded and relocated in memory as in the x86 case. We then pass
control to the decompressing code that appears to succeed. However, once
it has finished and "Parsing ELF file..." step has been run, the next
step "Booting the kernel..." crashes with a CPU Triple-Fault.
This problem **DOES NOT HAPPEN** when booting from GRUB.
Log excerpt from Bochs:
<snip>
00089459736i[BIOS ] Booting from 07c0:0000
00089782775i[SER ] com1: FIFO enabled
00095994535i[BIOS ] int13_harddisk: function 41, unmapped device for ELDL=81
00095998517i[BIOS ] int13_harddisk: function 08, unmapped device for ELDL=81
00397139785i[BIOS ] KBD: unsupported int 16h function 03
00397143625i[BIOS ] *** int 15h function AX=e980, BX=0000 not yet supported!
00523008104e[CPU0 ] interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x0
00523008104e[CPU0 ] interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x0
00523008104i[CPU0 ] CPU is in compatibility mode (active)
00523008104i[CPU0 ] CS.mode = 32 bit
00523008104i[CPU0 ] SS.mode = 32 bit
00523008104i[CPU0 ] EFER = 0x00000500
00523008104i[CPU0 ] | RAX=00000000e0000011 RBX=0000000000000000
00523008104i[CPU0 ] | RCX=0000000000000000 RDX=0000000000000000
00523008104i[CPU0 ] | RSP=00000000004f8000 RBP=000000000082e003
00523008104i[CPU0 ] | RSI=0000000000099800 RDI=00000000c0611000
00523008104i[CPU0 ] | R8=0000000000109000 R9=0000000000009020
00523008104i[CPU0 ] | R10=00000000000007e3 R11=000000000000e958
00523008104i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
00523008104i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
00523008104i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf af PF cf
00523008104i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00523008104i[CPU0 ] | CS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00523008104i[CPU0 ] | DS:0018( 0003| 0| 0) 00000000 ffffffff 1 1
00523008104i[CPU0 ] | SS:0018( 0003| 0| 0) 00000000 ffffffff 1 1
00523008104i[CPU0 ] | ES:0018( 0003| 0| 0) 00000000 ffffffff 1 1
00523008104i[CPU0 ] | FS:0018( 0003| 0| 0) 00000000 ffffffff 1 1
00523008104i[CPU0 ] | GS:0018( 0003| 0| 0) 00000000 ffffffff 1 1
00523008104i[CPU0 ] | MSR_FS_BASE:0000000000000000
00523008104i[CPU0 ] | MSR_GS_BASE:0000000000000000
00523008104i[CPU0 ] | RIP=0000000000409327 (0000000000409327)
00523008104i[CPU0 ] | CR0=0xe0000011 CR2=0x0000000000409327
00523008104i[CPU0 ] | CR3=0x005b5000 CR4=0x000000a0
00523008104i[CPU0 ] 0x0000000000409327: (instruction unavailable) page not present
00523008104p[CPU0 ] >>PANIC<< exception(): 3rd (13) exception with no resolution
<snip>
---
boot/freeldr/freeldr/arch/realmode/amd64.S | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/boot/freeldr/freeldr/arch/realmode/amd64.S b/boot/freeldr/freeldr/arch/realmode/amd64.S
index 0a97afd402d..ea1494f6b80 100644
--- a/boot/freeldr/freeldr/arch/realmode/amd64.S
+++ b/boot/freeldr/freeldr/arch/realmode/amd64.S
@@ -160,6 +160,12 @@ CheckFor64BitSupport:
.ascii "PAE or PGE not set.", CR, LF, NUL
.CheckForLongMode:
+ /* Check whether extended functions are supported */
+ mov eax, HEX(80000000)
+ cpuid
+ cmp eax, HEX(80000000) // Any function > 0x80000000 ?
+ jbe .NoLongMode // If not, no long mode.
+ /* Check whether the CPU supports Long Mode */
xor edx, edx
mov eax, HEX(80000001)
cpuid
@@ -167,6 +173,7 @@ CheckFor64BitSupport:
test edx, edx
jnz .Success
+.NoLongMode:
mov si, offset .Msg_NoLongMode
call writestr
popad
@@ -240,6 +247,18 @@ BuildPageTables:
/* This is the entry point from long mode */
RealModeEntryPoint:
+
+ /* Disable long mode */
+ mov ecx, MSR_EFER
+ rdmsr
+ and eax, HEX(0FFFFFEFF) // ~0100
+ wrmsr
+
+ /* Mask PAE and PGE out */
+ mov eax, cr4
+ and eax, HEX(0FFFFFF5F) // ~00A0
+ mov cr4, eax
+
/* Disable Protected Mode */
mov eax, cr0
and eax, HEX(0FFFFFFFE) // ~0x00000001
@@ -295,6 +314,8 @@ ExitToLongMode:
mov word ptr ds:[stack16], sp
/* Set PAE and PGE: 10100000b */
+ // mov eax, cr4
+ // or eax, HEX(00A0)
mov eax, HEX(00A0)
mov cr4, eax
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;