[FREELDR] linuxboot: It doesn't need the BIOS boot drive number and partition.

Also document a little bit the RootDevice field in the boot sector;
add SAL2 annotations.
This commit is contained in:
Hermès Bélusca-Maïto 2024-04-13 11:54:06 +02:00
parent c25a0e1919
commit e5517176b8
No known key found for this signature in database
GPG Key ID: 3B2539C65E7B93D0
4 changed files with 51 additions and 87 deletions

View File

@ -23,8 +23,6 @@
EXTERN DiskStopFloppyMotor:PROC
EXTERN Relocator16Boot:PROC
EXTERN FrldrBootDrive:BYTE
EXTERN FrldrBootPartition:DWORD
.code64
@ -32,12 +30,11 @@ Regs:
.space REGS_SIZE
/*
* VOID __cdecl BootLinuxKernel(
* IN ULONG KernelSize<ecx>,
* IN PVOID KernelCurrentLoadAddress<rdx>,
* IN PVOID KernelTargetLoadAddress<r8>,
* IN UCHAR DriveNumber<r9b>,
* IN ULONG PartitionNumber<rsp+40>);
* VOID __cdecl
* BootLinuxKernel(
* _In_ ULONG KernelSize<ecx>,
* _In_ PVOID KernelCurrentLoadAddress<rdx>,
* _In_ PVOID KernelTargetLoadAddress<r8>);
*/
PUBLIC BootLinuxKernel
BootLinuxKernel:
@ -47,7 +44,6 @@ BootLinuxKernel:
mov dword ptr [r11 + 8], ecx
mov qword ptr [r11 + 16], rdx
mov qword ptr [r11 + 24], r8
mov byte ptr [r11 + 32], r9b
/* Save non-volatile registers */
push rsi
@ -67,25 +63,6 @@ BootLinuxKernel:
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 [r11 + 32]
test dl, dl
jnz set_part
mov dl, byte ptr /*ds:*/[FrldrBootDrive]
/* Set the boot partition */
set_part:
mov eax, dword ptr [r11 + 40]
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

View File

@ -23,8 +23,6 @@
EXTERN _DiskStopFloppyMotor:PROC
EXTERN _Relocator16Boot:PROC
EXTERN _FrldrBootDrive:BYTE
EXTERN _FrldrBootPartition:DWORD
.code32
@ -32,12 +30,11 @@ Regs:
.space REGS_SIZE
/*
* VOID __cdecl BootLinuxKernel(
* IN ULONG KernelSize,
* IN PVOID KernelCurrentLoadAddress,
* IN PVOID KernelTargetLoadAddress,
* IN UCHAR DriveNumber,
* IN ULONG PartitionNumber);
* VOID __cdecl
* BootLinuxKernel(
* _In_ ULONG KernelSize,
* _In_ PVOID KernelCurrentLoadAddress,
* _In_ PVOID KernelTargetLoadAddress);
*/
PUBLIC _BootLinuxKernel
_BootLinuxKernel:
@ -52,25 +49,6 @@ _BootLinuxKernel:
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

View File

@ -129,18 +129,17 @@ typedef struct
#include <poppack.h>
// Implemented in linux.S
VOID __cdecl BootLinuxKernel(
IN ULONG KernelSize,
IN PVOID KernelCurrentLoadAddress,
IN PVOID KernelTargetLoadAddress,
IN UCHAR DriveNumber,
IN ULONG PartitionNumber);
VOID __cdecl
BootLinuxKernel(
_In_ ULONG KernelSize,
_In_ PVOID KernelCurrentLoadAddress,
_In_ PVOID KernelTargetLoadAddress);
ARC_STATUS
LoadAndBootLinux(
IN ULONG Argc,
IN PCHAR Argv[],
IN PCHAR Envp[]);
_In_ ULONG Argc,
_In_ PCHAR Argv[],
_In_ PCHAR Envp[]);
#endif /* _M_IX86 || _M_AMD64 */

View File

@ -20,6 +20,7 @@
/*
* The x86 Linux Boot Protocol is explained at:
* https://www.kernel.org/doc/Documentation/x86/boot.txt
* https://www.linux.it/~rubini/docs/boot/boot.html
*/
#if defined(_M_IX86) || defined(_M_AMD64)
@ -84,21 +85,29 @@ RemoveQuotes(
ARC_STATUS
LoadAndBootLinux(
IN ULONG Argc,
IN PCHAR Argv[],
IN PCHAR Envp[])
_In_ ULONG Argc,
_In_ PCHAR Argv[],
_In_ PCHAR Envp[])
{
ARC_STATUS Status;
PCSTR Description;
PCSTR ArgValue;
PCSTR BootPath;
UCHAR DriveNumber = 0;
ULONG PartitionNumber = 0;
ULONG LinuxKernel = 0;
ULONG LinuxInitrdFile = 0;
FILEINFORMATION FileInfo;
CHAR ArcPath[MAX_PATH];
#if DBG
/* Ensure the boot type is the one expected */
ArgValue = GetArgumentValue(Argc, Argv, "BootType");
if (!ArgValue || !*ArgValue || _stricmp(ArgValue, "Linux") != 0)
{
ERR("Unexpected boot type '%s', aborting\n", ArgValue ? ArgValue : "n/a");
return EINVAL;
}
#endif
Description = GetArgumentValue(Argc, Argv, "LoadIdentifier");
if (Description && *Description)
RtlStringCbPrintfA(LinuxBootDescription, sizeof(LinuxBootDescription), "Loading %s...", Description);
@ -125,10 +134,10 @@ LoadAndBootLinux(
ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
if (ArgValue && *ArgValue)
{
DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
UCHAR DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
/* Retrieve the boot partition (not optional and cannot be zero) */
PartitionNumber = 0;
ULONG PartitionNumber = 0;
ArgValue = GetArgumentValue(Argc, Argv, "BootPartition");
if (ArgValue && *ArgValue)
PartitionNumber = atoi(ArgValue);
@ -152,17 +161,6 @@ 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)
@ -240,9 +238,22 @@ LoadAndBootLinux(
goto LinuxBootFailed;
}
// If the default root device is set to FLOPPY (0000h), change to /dev/fd0 (0200h)
if (LinuxBootSector->RootDevice == 0x0000)
LinuxBootSector->RootDevice = 0x0200;
/*
* If the default root device is set to FLOPPY (0000h), change to /dev/fd0 (0200h).
* For a list of majors, see
* https://github.com/torvalds/linux/blob/master/include/uapi/linux/major.h
* For some examples of (decoded) root devices values, see
* https://github.com/torvalds/linux/blob/cc89c63e2/include/linux/root_dev.h
*
* NOTE: The RootDevice field is deprecated since commits
* https://github.com/torvalds/linux/commit/079f85e62
* https://github.com/torvalds/linux/commit/7448e8e5d
*/
#define NODEV 0
#define FLOPPY_MAJOR 2
#define makedev(maj, min) (((maj) << 8) | (min))
if (LinuxBootSector->RootDevice == NODEV)
LinuxBootSector->RootDevice = makedev(FLOPPY_MAJOR, 0);
if (LinuxSetupSector->Version >= 0x0202)
{
@ -271,8 +282,7 @@ LoadAndBootLinux(
BootLinuxKernel(LinuxKernelSize, LinuxKernelLoadAddress,
(LinuxSetupSector->LoadFlags & LINUX_FLAG_LOAD_HIGH)
? (PVOID)LINUX_KERNEL_LOAD_ADDRESS /* == 0x100000 */
: (PVOID)0x10000,
DriveNumber, PartitionNumber);
: (PVOID)0x10000);
/* Must not return! */
return ESUCCESS;