https://git.reactos.org/?p=reactos.git;a=commitdiff;h=8e2d1b358c91b7e91fb8a…
commit 8e2d1b358c91b7e91fb8aa093a2e5bb2ee474564
Author: Curtis Wilson <cwilson2016(a)outlook.com>
AuthorDate: Tue Mar 18 17:05:06 2025 -0400
Commit: GitHub <noreply(a)github.com>
CommitDate: Tue Mar 18 22:05:06 2025 +0100
[PING] Update SendBuffer fill method (#7782)
The ping utility found in various versions of Windows fills the optional
data field in the ICMP echo request structure with ASCII characters from
'a' to 'w' wrapping back around until SendBuffer is full.
Future TO-DO: Compare ReplyBuffer data to SendBuffer.
---
base/applications/network/ping/ping.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/base/applications/network/ping/ping.c b/base/applications/network/ping/ping.c
index 17afdfc5738..d0ebc0397ae 100644
--- a/base/applications/network/ping/ping.c
+++ b/base/applications/network/ping/ping.c
@@ -432,7 +432,11 @@ Ping(void)
exit(1);
}
- ZeroMemory(SendBuffer, RequestSize);
+ /* Windows ping utility fills the optional data field with
+ * ASCII characters from 'a' to 'w', wrapping back around
+ * until SendBuffer is full. */
+ for (ULONG i = 0; i < RequestSize; i++)
+ ((PUCHAR)SendBuffer)[i] = (UCHAR)('a' + (i % ('w' - 'a' + 1)));
}
if (Family == AF_INET6)
@@ -483,6 +487,7 @@ Ping(void)
ReplyBuffer, ReplySize, Timeout);
}
+ /* TODO: Compare ReplyBuffer data to SendBuffer. */
free(SendBuffer);
if (Status == 0)
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ddf55b3772b4257a4c2de…
commit ddf55b3772b4257a4c2decbeccc0d61c47cf42af
Author: Daniel Victor <ilauncherdeveloper(a)gmail.com>
AuthorDate: Tue Mar 18 17:53:47 2025 -0300
Commit: GitHub <noreply(a)github.com>
CommitDate: Tue Mar 18 21:53:47 2025 +0100
[BOOTSECT][FREELDR] Rewrite the Ext bootsector (#7544)
Rewrite the Ext bootsector because the older one was broken and had no compatibility with Ext4 extents.
Introduce a 3rd-stage bootsector for complex code.
CORE-14235
- Why was the previous bootsector broken?
Because of hardcoded inode size, hardcoded freeldr base address, etc.
- Why is there a extldr.sys?
The extldr.sys was introduced because the limited code space in the bootsector
prevents adding new features, such as Ext4 full extents support.
- What is extldr.sys and What does it do?
It is the helper file for the Ext bootsector and that is necessary for adding
Ext4 support. It locates the freeldr.sys file, loads it into memory and runs it.
---
boot/freeldr/bootsect/CMakeLists.txt | 6 +-
boot/freeldr/bootsect/ext.S | 726 +++++++++++++++++++++++++++++++++++
boot/freeldr/bootsect/ext2.S | 688 ---------------------------------
boot/freeldr/bootsect/extldr.S | 583 ++++++++++++++++++++++++++++
4 files changed, 1313 insertions(+), 690 deletions(-)
diff --git a/boot/freeldr/bootsect/CMakeLists.txt b/boot/freeldr/bootsect/CMakeLists.txt
index a46c9066c6a..986d399d13e 100644
--- a/boot/freeldr/bootsect/CMakeLists.txt
+++ b/boot/freeldr/bootsect/CMakeLists.txt
@@ -4,7 +4,8 @@ include_directories(${REACTOS_SOURCE_DIR}/boot/freeldr)
if(ARCH STREQUAL "i386" OR ARCH STREQUAL "amd64")
CreateBootSectorTarget(dosmbr ${CMAKE_CURRENT_SOURCE_DIR}/dosmbr.S ${CMAKE_CURRENT_BINARY_DIR}/dosmbr.bin 7c00)
- CreateBootSectorTarget(ext2 ${CMAKE_CURRENT_SOURCE_DIR}/ext2.S ${CMAKE_CURRENT_BINARY_DIR}/ext2.bin 0)
+ CreateBootSectorTarget(ext ${CMAKE_CURRENT_SOURCE_DIR}/ext.S ${CMAKE_CURRENT_BINARY_DIR}/ext.bin 7c00)
+ CreateBootSectorTarget(extldr ${CMAKE_CURRENT_SOURCE_DIR}/extldr.S ${CMAKE_CURRENT_BINARY_DIR}/extldr.sys 8000)
CreateBootSectorTarget(fat ${CMAKE_CURRENT_SOURCE_DIR}/fat.S ${CMAKE_CURRENT_BINARY_DIR}/fat.bin 7c00)
CreateBootSectorTarget(fat32 ${CMAKE_CURRENT_SOURCE_DIR}/fat32.S ${CMAKE_CURRENT_BINARY_DIR}/fat32.bin 7c00)
@@ -31,7 +32,8 @@ if(ARCH STREQUAL "i386" OR ARCH STREQUAL "amd64")
CreateBootSectorTarget(isombr ${CMAKE_CURRENT_SOURCE_DIR}/isombr.S ${CMAKE_CURRENT_BINARY_DIR}/isombr.bin 7000)
add_cd_file(TARGET dosmbr DESTINATION loader NO_CAB FILE ${CMAKE_CURRENT_BINARY_DIR}/dosmbr.bin FOR bootcd regtest)
- add_cd_file(TARGET ext2 DESTINATION loader NO_CAB FILE ${CMAKE_CURRENT_BINARY_DIR}/ext2.bin FOR bootcd regtest)
+ add_cd_file(TARGET ext DESTINATION loader NO_CAB FILE ${CMAKE_CURRENT_BINARY_DIR}/ext.bin FOR bootcd regtest)
+ add_cd_file(TARGET extldr DESTINATION loader NO_CAB FILE ${CMAKE_CURRENT_BINARY_DIR}/extldr.sys FOR bootcd regtest)
add_cd_file(TARGET btrfsvbr DESTINATION loader NO_CAB FILE ${CMAKE_CURRENT_BINARY_DIR}/btrfs.bin FOR bootcd regtest)
add_cd_file(TARGET fat DESTINATION loader NO_CAB FILE ${CMAKE_CURRENT_BINARY_DIR}/fat.bin FOR bootcd regtest)
add_cd_file(TARGET fat32 DESTINATION loader NO_CAB FILE ${CMAKE_CURRENT_BINARY_DIR}/fat32.bin FOR bootcd regtest)
diff --git a/boot/freeldr/bootsect/ext.S b/boot/freeldr/bootsect/ext.S
new file mode 100644
index 00000000000..4a449b632d4
--- /dev/null
+++ b/boot/freeldr/bootsect/ext.S
@@ -0,0 +1,726 @@
+/*
+ * PROJECT: FreeLoader
+ * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE: EXTFS volume boot sector
+ * COPYRIGHT: Copyright 2002-2003 Brian Palmer <brianp(a)sginet.com>
+ * Copyright 2024-2025 Daniel Victor <ilauncherdeveloper(a)gmail.com>
+ */
+
+#include <asm.inc>
+#include <freeldr/include/arch/pc/x86common.h>
+
+// Boot sector constants
+#define BOOTSECTOR_BASE_ADDRESS HEX(7C00)
+#define EXTLDR_BOOTSECTOR_SIZE 1024
+#define EXT_POINTER_SIZE 4
+#define EXT_EXTENT_SIZE 12
+
+// Maximum extent values
+#define EXT_EXTENT_MAX_LEVEL 5
+#define EXT_EXTENT_MAX_LENGTH 32768
+
+// Group descriptor offsets
+#define EXT_GROUP_DESC_INODE_TABLE_OFFSET 8
+
+// Extent offsets
+#define EXT_EXTENT_HEADER_ENTRIES_OFFSET 2
+#define EXT_EXTENT_HEADER_DEPTH_OFFSET 6
+#define EXT_EXTENT_INDEX_LEAF_OFFSET 4
+#define EXT_EXTENT_LENGTH_OFFSET 4
+#define EXT_EXTENT_START_OFFSET 8
+
+// Inode offsets
+#define EXT_INODE_SIZE_OFFSET 4
+#define EXT_INODE_FLAGS_OFFSET 32
+#define EXT_INODE_BLOCK_POINTER_OFFSET 40
+
+// Directory entry offsets
+#define EXT_DIRECTORY_ENTRY_SIZE_OFFSET 4
+#define EXT_DIRECTORY_ENTRY_NAME_LENGTH_OFFSET 6
+#define EXT_DIRECTORY_ENTRY_NAME_OFFSET 8
+
+// Inode flags
+#define EXT_INODE_FLAG_EXTENTS HEX(80000)
+
+// Inode blocks constants
+#define EXT_INODE_BLOCKS 12
+#define EXT_INODE_INDIRECT_BLOCKS 3
+
+// Root Inode
+#define EXT_ROOT_INODE 2
+
+// Inode address
+#define EXT_INODE_ADDRESS HEX(9000)
+
+// Data block addresses
+#define EXT_BLOCK_ADDRESS HEX(1000)
+#define EXT_BLOCK2_ADDRESS HEX(2000)
+#define EXT_BLOCK3_ADDRESS HEX(3000)
+#define EXT_BLOCK4_ADDRESS HEX(4000)
+#define EXT_BLOCK5_ADDRESS HEX(5000)
+#define EXT_BLOCK6_ADDRESS HEX(6000)
+#define EXT_BLOCK7_ADDRESS HEX(A000)
+
+// Inode types
+#define EXT_INODE_TYPE_MASK HEX(F000)
+#define EXT_INODE_TYPE_REGULAR HEX(8000)
+
+// File size limit
+#define EXT_INODE_DATA_SIZE_LIMIT HEX(F000)
+
+// Offset of functions addresses that will be used by the extldr.sys 3rd-stage bootsector
+#define ExtReadBlockOffset 2
+#define ExtReadInodeOffset 4
+#define DisplayItAndRebootOffset 6
+#define PutCharsOffset 8
+
+// Boot sector stack constants
+#define BOOTSECTOR_STACK_TEMP_VARIABLES 2
+#define BOOTSECTOR_STACK_TEMP_VARIABLES_SIZE (4 * BOOTSECTOR_STACK_TEMP_VARIABLES)
+#define BOOTSECTOR_STACK_OFFSET (8 + BOOTSECTOR_STACK_TEMP_VARIABLES_SIZE)
+#define BOOTSECTOR_STACK_BASE (BOOTSECTOR_BASE_ADDRESS - BOOTSECTOR_STACK_OFFSET)
+#define BP_REL(x) ss:[bp + (x - BOOTSECTOR_BASE_ADDRESS)]
+
+// Temporary variables
+#define ExtFileSizeState ((BOOTSECTOR_STACK_BASE + BOOTSECTOR_STACK_TEMP_VARIABLES_SIZE) - 4)
+#define LBASectorsRead (ExtFileSizeState - 4)
+
+.code16
+
+#ifndef INCLUDED_ASM
+
+start:
+ jmp short main
+ nop
+
+// Fields that will be changed by the installer
+BootDrive:
+ .byte HEX(FF)
+ExtVolumeStartSector:
+ .long 263088 // Start sector of the ext2 volume
+ExtBlockSize:
+ .long 2 // Block size in sectors
+ExtBlockSizeInBytes:
+ .long 1024 // Block size in bytes
+ExtPointersPerBlock:
+ .long 256 // Number of block pointers that can be contained in one block
+ExtGroupDescSize:
+ .long 32 // Size of Group Descriptor
+ExtFirstDataBlock:
+ .long 2 // First data block (2 for 1024-byte blocks, 1 for bigger sizes)
+ExtInodeSize:
+ .long 128 // Size of Inode
+ExtInodesPerGroup:
+ .long 2048 // Number of inodes per group
+
+// File variables
+ExtFileSize:
+ .long 0 // File size in bytes
+ExtFileAddress:
+ .long FREELDR_BASE // File address
+ExtFileAddressOld:
+ .long FREELDR_BASE // Old file address
+
+// Inode variables
+ExtReadInodeGroup:
+ .long 0
+ExtReadInodeIndex:
+ .long 0
+ExtReadInodeGroupBlock:
+ .long 0
+ExtReadInodeIndexBlock:
+ .long 0
+ExtReadInodeGroupOffset:
+ .word 0
+ExtReadInodeIndexOffset:
+ .word 0
+
+main:
+ xor ax, ax // Setup segment registers
+ mov ds, ax // Make DS correct
+ mov es, ax // Make ES correct
+ mov ss, ax // Make SS correct
+ mov bp, BOOTSECTOR_BASE_ADDRESS
+ mov sp, bp // Setup a stack
+ sub sp, BOOTSECTOR_STACK_OFFSET
+
+ // Save the function addresses so the helper code knows where to call them
+ mov word ptr ss:[bp-ExtReadBlockOffset], offset ExtReadBlock
+ mov word ptr ss:[bp-ExtReadInodeOffset], offset ExtReadInode
+ mov word ptr ss:[bp-DisplayItAndRebootOffset], offset DisplayItAndReboot
+ mov word ptr ss:[bp-PutCharsOffset], offset PutChars
+
+ mov si, offset BootDrive
+ cmp byte ptr [si], HEX(0ff) // If they have specified a boot drive then use it
+ jne CheckInt13hExtensions
+
+ mov byte ptr [si], dl // Save the boot drive
+
+// Now check if this computer supports extended reads. This boot sector will not work without it.
+CheckInt13hExtensions:
+ mov ah, HEX(41) // AH = 41h
+ mov bx, HEX(55aa) // BX = 55AAh
+ int HEX(13) // IBM/MS INT 13 Extensions - INSTALLATION CHECK
+ jc PrintDiskError // CF set on error (extensions not supported)
+ cmp bx, HEX(aa55) // BX = AA55h if installed
+ jne PrintDiskError
+ test cl, 1 // si = API subset support bitmap
+ jz PrintDiskError // Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
+
+LoadExtraBootCode:
+ // First we have to load our extra boot code at
+ // sector 1 into memory at [0000:7e00h]
+ xor eax, eax
+ inc eax
+ mov cx, 1
+ xor bx, bx
+ mov es, bx // Read sector to [0000:7e00h]
+ mov bx, HEX(7e00)
+ call ReadSectors
+
+ jmp LoadRootDirectory
+
+// Reads logical sectors into ES:[BX]
+// EAX has logical sector number to read
+// CX has number of sectors to read
+ReadSectors:
+ push es
+ add eax, dword ptr BP_REL(ExtVolumeStartSector) // Add the start of the volume
+ // If at all possible we want to use LBA routines because
+ // they are optimized to read more than 1 sector per read
+
+ReadSectorsLBA:
+ pushad // Save logical sector number & sector count
+
+ cmp cx, 64 // Since the LBA calls only support 0x7F sectors at a time we will limit ourselves to 64
+ jbe ReadSectorsSetupDiskAddressPacket // If we are reading less than 65 sectors then just do the read
+ mov cx, 64 // Otherwise read only 64 sectors on this loop iteration
+
+ReadSectorsSetupDiskAddressPacket:
+ movzx ecx, cx
+ mov dword ptr BP_REL(LBASectorsRead), ecx
+ data32 push 0
+ push eax // Put 64-bit logical block address on stack
+ push es // Put transfer segment on stack
+ push bx // Put transfer offset on stack
+ push cx // Set transfer count
+ push 16 // Set size of packet to 10h
+ mov si, sp // Setup disk address packet on stack
+
+ mov dl, byte ptr BP_REL(BootDrive) // Drive number
+ mov ah, HEX(42) // Int 13h, AH = 42h - Extended Read
+ int HEX(13) // Call BIOS
+ jc PrintDiskError // If the read failed then abort
+
+ add sp, 16 // Remove disk address packet from stack
+
+ popad // Restore sector count & logical sector number
+
+ push bx
+ mov ebx, dword ptr BP_REL(LBASectorsRead)
+ add eax, ebx // Increment sector to read
+ shl ebx, 5
+ mov dx, es
+ add dx, bx // Setup read buffer for next sector
+ mov es, dx
+ pop bx
+
+ sub cx, word ptr BP_REL(LBASectorsRead)
+ jnz ReadSectorsLBA // Read next sector
+
+ pop es
+ ret
+
+// Displays a disk error message
+// And reboots
+PrintDiskError:
+ mov si, offset msgDiskError // Bad boot disk message
+ call PutChars // Display it
+
+Reboot:
+ mov si, offset msgAnyKey // Press any key message
+ call PutChars // Display it
+ xor ax, ax
+ int HEX(16) // Wait for a keypress
+ int HEX(19) // Reboot
+
+.PutCharsLoop:
+ mov ah, HEX(0E)
+ mov bx, 7
+ int HEX(10)
+PutChars:
+ lodsb
+ or al, al
+ jnz .PutCharsLoop
+ ret
+
+SwapESWithDS:
+ // Swap ES and DS
+ push es
+ push ds
+ pop es
+ pop ds
+ ret
+
+ExtReadGroupDescriptor:
+ mov eax, dword ptr BP_REL(ExtReadInodeGroupBlock) // Get Inode group block
+ add eax, dword ptr BP_REL(ExtFirstDataBlock) // Add the Group Descriptor offset
+ call ExtSetInodeSegment
+
+ExtReadBlock:
+ xor edx, edx
+ mov ecx, dword ptr BP_REL(ExtBlockSize)
+ mul ecx
+ jmp ReadSectors
+
+// EAX
+ExtCalculateBlock:
+ xor edx, edx // Clear EDX before division
+ div dword ptr BP_REL(ExtBlockSizeInBytes) // Inode /= ExtBlockSizeInBytes
+ mov dword ptr ds:[bp + si], eax // Store the Inode block
+ ret
+
+// SI, DI
+ExtCalculateOffset:
+ add bx, bp // Sum BX with BP for absolute address
+ xor edx, edx // Clear EDX before multiplication
+ mov eax, dword ptr ds:[bp + si] // Get the Inode block
+ mul dword ptr BP_REL(ExtBlockSizeInBytes) // Inode *= ExtBlockSizeInBytes
+ mov ecx, dword ptr ds:[bx] // Get the Inode
+ sub ecx, eax // Subtract the original Inode with rounded down Inode
+ mov word ptr ds:[bp + di], cx // Store the rounded down Inode
+ ret
+
+ExtSetOldFileSegment:
+ mov ebx, dword ptr BP_REL(ExtFileAddressOld) // Get the EXT old file address
+ jmp .ExtSegSkip
+ExtSetFileSegment:
+ mov ebx, dword ptr BP_REL(ExtFileAddress) // Get the EXT file address
+.ExtSegSkip:
+ shr ebx, 4 // Shift four bits to the right to get segment
+ jmp .ExtSkip
+ExtSetInodeSegment:
+ mov bx, EXT_INODE_ADDRESS / 16 // Get the EXT inode address
+.ExtSkip:
+ mov es, bx // Set ES
+ xor bx, bx // Clear BX
+ ret
+
+// Read the Inode in EAX register
+ExtReadInode:
+ xor edx, edx // Clear EDX before division
+ dec eax // Inode--
+ div dword ptr BP_REL(ExtInodesPerGroup) // Inode /= ExtInodesPerGroup
+ mov dword ptr BP_REL(ExtReadInodeGroup), eax // Store the Inode group
+ mov dword ptr BP_REL(ExtReadInodeIndex), edx // Store the Inode index
+
+ xor edx, edx // Clear EDX before multiplication
+ mul dword ptr BP_REL(ExtGroupDescSize) // Inode group *= ExtGroupDescSize
+ mov dword ptr BP_REL(ExtReadInodeGroup), eax // Store the precalculated Inode group
+
+ xor edx, edx // Clear EDX before multiplication
+ mov eax, dword ptr BP_REL(ExtReadInodeIndex) // Get the read Inode index
+ mul dword ptr BP_REL(ExtInodeSize) // Inode group *= ExtInodeSize
+ mov dword ptr BP_REL(ExtReadInodeIndex), eax // Store the Inode index
+
+ // Calculate the Inode index block
+ mov si, offset ExtReadInodeIndexBlock - start
+ call ExtCalculateBlock
+
+ // Calculate the Inode group block
+ mov eax, dword ptr BP_REL(ExtReadInodeGroup)
+ mov si, offset ExtReadInodeGroupBlock - start
+ call ExtCalculateBlock
+
+ // Calculate the Inode group offset
+ mov bx, offset ExtReadInodeGroup - start
+ mov si, offset ExtReadInodeGroupBlock - start
+ mov di, offset ExtReadInodeGroupOffset - start
+ call ExtCalculateOffset
+
+ // Calculate the Inode index offset
+ mov bx, offset ExtReadInodeIndex - start
+ mov si, offset ExtReadInodeIndexBlock - start
+ mov di, offset ExtReadInodeIndexOffset - start
+ call ExtCalculateOffset
+
+ // Read group descriptor
+ call ExtReadGroupDescriptor
+
+ // Set the offset address
+ mov si, word ptr BP_REL(ExtReadInodeGroupOffset)
+
+ // Get InodeTable field from the ExtGroupDescriptor structure
+ mov eax, dword ptr es:[si + EXT_GROUP_DESC_INODE_TABLE_OFFSET]
+
+ // Sum EAX with Inode index block
+ add eax, dword ptr BP_REL(ExtReadInodeIndexBlock)
+
+ jmp ExtReadBlock
+
+msgDiskError:
+ .ascii "Disk error", CR, LF, NUL
+msgAnyKey:
+ .ascii "Press any key", CR, LF, NUL
+
+.org 509
+
+BootPartition:
+ .byte 0
+
+.word HEX(AA55) // BootSector signature
+
+// End of bootsector
+//
+// Now starts the extra boot code that we will store
+// at sector 1 on a EXT volume
+
+LoadRootDirectory:
+ mov al, EXT_ROOT_INODE // Put the root directory inode number in AL
+ movzx eax, al // Convert AL to EAX
+
+ call ExtReadInode // Read the inode
+ call BasicReadFile // Load the directory entries using basic function
+ call SearchFile // Find the extended loader and run it
+
+ jmp ExtLdrPrintFileNotFound // If the extended loader wasn't found, display an error
+
+ExtInodeDetectExtentsFlag:
+ mov eax, es:[si + EXT_INODE_FLAGS_OFFSET]
+ test eax, EXT_INODE_FLAG_EXTENTS
+ ret
+
+ExtUpdateFileSize:
+ mov eax, dword ptr BP_REL(ExtBlockSizeInBytes)
+
+ExtAdjustFileSize:
+ // Update the file size
+ sub dword ptr BP_REL(ExtFileSizeState), eax
+ add dword ptr BP_REL(ExtFileAddress), eax
+ ret
+
+ExtReadFileDone:
+ push eax
+ mov eax, dword ptr BP_REL(ExtFileSizeState)
+ cmp eax, dword ptr BP_REL(ExtBlockSizeInBytes)
+ pop eax
+ ret
+
+ExtFileReadBlocks:
+ push es
+.FRLoop:
+ // Check if there is no more blocks to read
+ call ExtReadFileDone
+ jb .FRDone
+
+ // If the block count is zero then do nothing
+ test bx, bx
+ jz .FRDone
+
+ // Read the block
+ pushad
+ call ExtSetFileSegment
+ call ExtReadBlock
+ popad
+
+ // Update the file size
+ call ExtUpdateFileSize
+
+ // Go to the next block and decrement the block count
+ inc eax
+ dec bx
+
+ // Loop until all blocks are read
+ jmp .FRLoop
+.FRDone:
+ pop es
+ ret
+
+BasicReadFileExtents:
+ // Add block pointer offset
+ add si, EXT_INODE_BLOCK_POINTER_OFFSET
+
+.DepthExtentsLoop:
+ // Load extent header depth
+ mov dx, word ptr es:[si + EXT_EXTENT_HEADER_DEPTH_OFFSET]
+
+ // Check if depth is zero
+ test dx, dx
+ jz .DepthExtentsDone
+
+ // Go to next extent
+ add si, EXT_EXTENT_SIZE
+
+ // Push all registers
+ pushad
+
+ // Read the extent block
+ mov eax, dword ptr es:[si + EXT_EXTENT_INDEX_LEAF_OFFSET]
+ call ExtSetInodeSegment
+ call ExtReadBlock
+
+ // Pop all registers
+ popad
+
+ // Reset SI
+ xor si, si
+
+ jmp .DepthExtentsLoop
+.DepthExtentsDone:
+ // Load extent header entries
+ mov cx, word ptr es:[si + EXT_EXTENT_HEADER_ENTRIES_OFFSET]
+
+.FinalExtentsLoop:
+ // Check if there is no more blocks to read
+ call ExtReadFileDone
+ jb .FinalExtentsDone
+
+ // Go to next extent
+ add si, EXT_EXTENT_SIZE
+
+ // Load extent length
+ mov bx, word ptr es:[si + EXT_EXTENT_LENGTH_OFFSET]
+ and ebx, HEX(FFFF)
+
+ // Check if extent is sparse
+ cmp bx, EXT_EXTENT_MAX_LENGTH
+ jbe .NotSparse
+
+ // Adjust sparse extent length
+ sub bx, EXT_EXTENT_MAX_LENGTH
+
+ // Adjust extent length to byte count
+ // by multiplying extent length to block size
+ xor edx, edx
+ mov eax, dword ptr BP_REL(ExtBlockSizeInBytes)
+ mul ebx
+
+ // Adjust file size for sparse extent
+ call ExtAdjustFileSize
+
+ jmp .FinalExtentsSkip
+
+.NotSparse:
+ // Read blocks from extent start
+ mov eax, dword ptr es:[si + EXT_EXTENT_START_OFFSET]
+ call ExtFileReadBlocks
+
+.FinalExtentsSkip:
+ // Loop to process next extent
+ loop .FinalExtentsLoop
+
+.FinalExtentsDone:
+ ret
+
+BasicReadFile:
+ push es
+ pushad
+ call ExtSetInodeSegment
+
+ // Set the correct Inode offset
+ mov si, word ptr BP_REL(ExtReadInodeIndexOffset)
+
+ // Set the old file address
+ mov eax, dword ptr BP_REL(ExtFileAddress)
+ mov dword ptr BP_REL(ExtFileAddressOld), eax
+
+ // Set the file size limit
+ mov eax, EXT_INODE_DATA_SIZE_LIMIT
+
+ // Load file size from Inode
+ mov ebx, dword ptr es:[si + EXT_INODE_SIZE_OFFSET]
+
+ // Compare and limit file size
+ cmp ebx, eax
+ jbe .BelowOrEqualSize
+ mov ebx, eax
+.BelowOrEqualSize:
+ // Store the file size in the ExtFileSize variable
+ mov dword ptr BP_REL(ExtFileSize), ebx
+
+ // Set rounded up file size
+ add ebx, dword ptr BP_REL(ExtBlockSizeInBytes)
+ dec ebx
+ mov dword ptr BP_REL(ExtFileSizeState), ebx
+
+ // Don't use the extents method if theres no extents flag
+ call ExtInodeDetectExtentsFlag
+ jz .NoExtents
+
+ // If this Inode use Extents mapping then use the extents method and skip the entire classic method
+ call BasicReadFileExtents
+ jmp .LDone
+
+.NoExtents:
+ // Set up for reading direct block addresses
+ xor ecx, ecx
+ mov cl, EXT_INODE_BLOCKS
+ add si, EXT_INODE_BLOCK_POINTER_OFFSET
+.LLoop:
+ call ExtSetInodeSegment
+
+ call ExtReadFileDone
+ jb .LDone
+
+ // Get the block address
+ mov eax, dword ptr es:[si]
+
+ // If the block address is zero, skip the block
+ test eax, eax
+ jz .LSkipBlock
+
+ // Set the file segment
+ call ExtSetFileSegment
+
+ // Read the block
+ call ExtReadBlock
+.LSkipBlock:
+ call ExtUpdateFileSize
+
+ // Increment block
+ add si, EXT_POINTER_SIZE
+
+ // Loop until all blocks are loaded
+ loop .LLoop
+.LDone:
+ popad
+ pop es
+ ret
+
+SearchFile:
+ call ExtSetOldFileSegment
+ call SwapESWithDS
+
+ xor si, si
+ mov dx, word ptr BP_REL(ExtFileSize)
+.FLoop:
+ mov eax, dword ptr ds:[si] // Load directory Inode
+
+ cmp si, dx // End of buffer reached?
+ jae .Done // Abort the search if yes
+
+ // Save SI
+ push si
+
+ test eax, eax // Check if Inode is zero
+ jz .Skip // Skip this entry if yes
+
+ mov di, offset ExtLdrFileName // Load target filename address
+ mov cx, offset ExtLdrFileNameEnd - ExtLdrFileName // Length of filename to compare
+ cmp byte ptr ds:[si + EXT_DIRECTORY_ENTRY_NAME_LENGTH_OFFSET], cl // Compare if both names have the same length
+ jnz .Skip // Skip this entry if yes
+ add si, EXT_DIRECTORY_ENTRY_NAME_OFFSET // Move to filename in entry
+ repe cmpsb // Compare filenames
+ pop si // Restore SI
+ jz LoadExtLdr // Found matching file
+ push si // Save SI
+
+.Skip:
+ // Restore SI
+ pop si
+
+ // Move to next directory entry and continue looping
+ add si, word ptr ds:[si + EXT_DIRECTORY_ENTRY_SIZE_OFFSET]
+ jmp .FLoop
+.Done:
+ ret
+
+LoadExtLdr:
+ // Swap ES and DS
+ call SwapESWithDS
+
+ push si // Save SI
+ mov si, offset msgLoadingExtLdr // Point SI to a loading message
+ call PutChars // Show the message
+ pop si // Restore SI
+
+ mov eax, dword ptr es:[si] // Load directory Inode
+ call ExtReadInode // Read the inode
+ mov si, word ptr BP_REL(ExtReadInodeIndexOffset) // Set the correct offset
+
+ // Get Inode type
+ mov ax, word ptr es:[si]
+ and ax, EXT_INODE_TYPE_MASK
+
+ cmp ax, EXT_INODE_TYPE_REGULAR // Check if regular file
+ jnz ExtLdrPrintRegFileError // If not, handle error
+
+ call BasicReadFile // Load the file using basic function
+ call ExtSetOldFileSegment // Set old file segment
+ call SwapESWithDS // Swap ES with DS before copy
+
+ // Copy the loaded file to 1KB ahead of this bootsector
+ xor si, si
+ mov di, offset ExtLdrEntryPoint
+ mov cx, EXTLDR_BOOTSECTOR_SIZE
+ rep movsb
+
+ ljmp16 0, ExtLdrEntryPoint
+
+ExtLdrPrintFileNotFound:
+ // Make DS correct, display it and reboot
+ call SwapESWithDS
+ mov si, offset msgExtLdr
+ jmp DisplayItAndReboot
+
+ExtLdrPrintRegFileError:
+ mov si, offset msgExtLdrNotRegularFile // ExtLdr not found message
+DisplayItAndReboot:
+ call PutChars // Display it
+ jmp Reboot
+
+ExtLdrFileName:
+ .ascii "extldr.sys"
+ExtLdrFileNameEnd:
+
+msgExtLdr:
+ .ascii "extldr.sys not found", CR, LF, NUL
+msgExtLdrNotRegularFile:
+ .ascii "extldr.sys is not a regular file", CR, LF, NUL
+msgLoadingExtLdr:
+ .ascii "Loading ExtLoader...", CR, LF, NUL
+
+.org 1022
+
+.word HEX(AA55) // BootSector signature
+
+ExtLdrEntryPoint:
+// ExtLdr is loaded here
+
+.endcode16
+
+END
+
+#else
+
+#define start BOOTSECTOR_BASE_ADDRESS
+
+#define BootDrive (start + 3)
+#define ExtVolumeStartSector (BootDrive + 1)
+#define ExtBlockSize (ExtVolumeStartSector + 4)
+#define ExtBlockSizeInBytes (ExtBlockSize + 4)
+#define ExtPointersPerBlock (ExtBlockSizeInBytes + 4)
+#define ExtGroupDescSize (ExtPointersPerBlock + 4)
+#define ExtFirstDataBlock (ExtGroupDescSize + 4)
+#define ExtInodeSize (ExtFirstDataBlock + 4)
+#define ExtInodesPerGroup (ExtInodeSize + 4)
+
+#define ExtFileSize (ExtInodesPerGroup + 4)
+#define ExtFileAddress (ExtFileSize + 4)
+#define ExtFileAddressOld (ExtFileAddress + 4)
+
+#define ExtReadInodeGroup (ExtFileAddressOld + 4)
+#define ExtReadInodeIndex (ExtReadInodeGroup + 4)
+#define ExtReadInodeGroupBlock (ExtReadInodeIndex + 4)
+#define ExtReadInodeIndexBlock (ExtReadInodeGroupBlock + 4)
+#define ExtReadInodeGroupOffset (ExtReadInodeIndexBlock + 4)
+#define ExtReadInodeIndexOffset (ExtReadInodeGroupOffset + 2)
+
+#define BootPartition (BootDrive + 506)
+
+#define ExtReadBlock word ptr ss:[bp-ExtReadBlockOffset]
+#define ExtReadInode word ptr ss:[bp-ExtReadInodeOffset]
+#define DisplayItAndReboot word ptr ss:[bp-DisplayItAndRebootOffset]
+#define PutChars word ptr ss:[bp-PutCharsOffset]
+
+#endif
diff --git a/boot/freeldr/bootsect/ext2.S b/boot/freeldr/bootsect/ext2.S
deleted file mode 100644
index bd3119c635f..00000000000
--- a/boot/freeldr/bootsect/ext2.S
+++ /dev/null
@@ -1,688 +0,0 @@
-// EXT2.ASM
-// EXT2 Boot Sector
-// Copyright (c) 2002, 2003 Brian Palmer
-
-// [bp-0x04] Here we will store the number of sectors per track
-// [bp-0x08] Here we will store the number of heads
-// [bp-0x0c] Here we will store the size of the disk as the BIOS reports in CHS form
-// [bp-0x10] Here we will store the number of LBA sectors read
-
-#include <asm.inc>
-.code16
-
-SECTORS_PER_TRACK = HEX(04)
-NUMBER_OF_HEADS = HEX(08)
-BIOS_CHS_DRIVE_SIZE = HEX(0C)
-LBA_SECTORS_READ = HEX(10)
-
-
-EXT2_ROOT_INO = 2
-EXT2_S_IFMT = HEX(0f0)
-EXT2_S_IFREG = HEX(080)
-
-
-//org 7c00h
-
-
-start:
- jmp short main
- nop
-
-BootDrive:
- .byte HEX(80)
-//BootPartition db 0 // Moved to end of boot sector to have a standard format across all boot sectors
-//SectorsPerTrack db 63 // Moved to [bp-SECTORS_PER_TRACK]
-//NumberOfHeads dw 16 // Moved to [bp-NUMBER_OF_HEADS]
-//BiosCHSDriveSize dd (1024 * 1024 * 63) // Moved to [bp-BIOS_CHS_DRIVE_SIZE]
-//LBASectorsRead dd 0 // Moved to [bp-LBA_SECTORS_READ]
-
-Ext2VolumeStartSector:
- .long 263088 // Start sector of the ext2 volume
-Ext2BlockSize:
- .long 2 // Block size in sectors
-Ext2BlockSizeInBytes:
- .long 1024 // Block size in bytes
-Ext2PointersPerBlock:
- .long 256 // Number of block pointers that can be contained in one block
-Ext2GroupDescPerBlock:
- .long 32 // Number of group descriptors per block
-Ext2FirstDataBlock:
- .long 1 // First data block (1 for 1024-byte blocks, 0 for bigger sizes)
-Ext2InodesPerGroup:
- .long 2048 // Number of inodes per group
-Ext2InodesPerBlock:
- .long 8 // Number of inodes per block
-
-Ext2ReadEntireFileLoadSegment:
- .word 0
-Ext2InodeIndirectPointer:
- .long 0
-Ext2InodeDoubleIndirectPointer:
- .long 0
-Ext2BlocksLeftToRead:
- .long 0
-
-main:
- xor ax,ax // Setup segment registers
- mov ds,ax // Make DS correct
- mov es,ax // Make ES correct
- mov ss,ax // Make SS correct
- mov bp, HEX(7c00)
- mov sp, HEX(7b00) // Setup a stack
-
- mov si, offset BootDrive
- cmp byte ptr [si], HEX(0ff) // If they have specified a boot drive then use it
- jne GetDriveParameters
-
- mov [si],dl // Save the boot drive
-
-
-GetDriveParameters:
- mov ah, 8
- mov dl,[si] // Get boot drive in dl
- int HEX(13) // Request drive parameters from the bios
- jnc CalcDriveSize // If the call succeeded then calculate the drive size
-
- // If we get here then the call to the BIOS failed
- // so just set CHS equal to the maximum addressable
- // size
- mov cx, HEX(0ffff)
- mov dh,cl
-
-CalcDriveSize:
- // Now that we have the drive geometry
- // lets calculate the drive size
- mov bl,ch // Put the low 8-bits of the cylinder count into BL
- mov bh,cl // Put the high 2-bits in BH
- shr bh,6 // Shift them into position, now BX contains the cylinder count
- and cl, HEX(3f) // Mask off cylinder bits from sector count
- // CL now contains sectors per track and DH contains head count
- movzx eax,dh // Move the heads into EAX
- movzx ebx,bx // Move the cylinders into EBX
- movzx ecx,cl // Move the sectors per track into ECX
- inc eax // Make it one based because the bios returns it zero based
- mov [bp-NUMBER_OF_HEADS],eax // Save number of heads
- mov [bp-SECTORS_PER_TRACK],ecx // Save number of sectors per track
- inc ebx // Make the cylinder count one based also
- mul ecx // Multiply heads with the sectors per track, result in edx:eax
- mul ebx // Multiply the cylinders with (heads * sectors) [stored in edx:eax already]
-
- // We now have the total number of sectors as reported
- // by the bios in eax, so store it in our variable
- mov [bp-BIOS_CHS_DRIVE_SIZE],eax
-
-
-LoadExtraBootCode:
- // First we have to load our extra boot code at
- // sector 1 into memory at [0000:7e00h]
- //mov eax,01h
- xor eax,eax
- inc eax // Read logical sector 1, EAX now = 1
- mov cx,1 // Read one sector
- mov bx, HEX(7e00) // Read sector to [0000:7e00h]
- call ReadSectors
-
- jmp LoadRootDirectory
-
-
-
-// Reads ext2 group descriptor into [7000:8000]
-// We read it to this arbitrary location so
-// it will not cross a 64k boundary
-// EAX has group descriptor number to read
-Ext2ReadGroupDesc:
- shl eax,5 // Group = (Group * sizeof(GROUP_DESCRIPTOR) /* 32 */)
- xor edx,edx
- div dword ptr [bp+Ext2GroupDescPerBlock] // Group = (Group / Ext2GroupDescPerBlock)
- add eax, dword ptr [bp+Ext2FirstDataBlock] // Group = Group + Ext2FirstDataBlock + 1
- inc eax // EAX now has the group descriptor block number
- // EDX now has the group descriptor offset in the block
-
- // Adjust the read offset so that the
- // group descriptor is read to 7000:8000
- mov ebx, HEX(78000)
- sub ebx,edx
- shr ebx,4
- mov es,bx
- xor bx,bx
-
-
- // Everything is now setup to call Ext2ReadBlock
- // Instead of using the call instruction we will
- // just put Ext2ReadBlock right after this routine
-
-// Reads ext2 block into ES:[BX]
-// EAX has logical block number to read
-Ext2ReadBlock:
- mov ecx, dword ptr [bp+Ext2BlockSize]
- mul ecx
- jmp ReadSectors
-
-// Reads ext2 inode into [6000:8000]
-// We read it to this arbitrary location so
-// it will not cross a 64k boundary
-// EAX has inode number to read
-Ext2ReadInode:
- dec eax // Inode = Inode - 1
- xor edx,edx
- div dword ptr [bp+Ext2InodesPerGroup] // Inode = (Inode / Ext2InodesPerGroup)
- mov ebx,eax // EBX now has the inode group number
- mov eax,edx
- xor edx,edx
- div dword ptr [bp+Ext2InodesPerBlock] // Inode = (Inode / Ext2InodesPerBlock)
- shl edx,7 // FIXME: InodeOffset *= 128 (make the array index a byte offset)
- // EAX now has the inode offset block number from inode table
- // EDX now has the inode offset in the block
-
- // Save the inode values and put the group
- // descriptor number in EAX and read it in
- push edx
- push eax
- mov eax,ebx
- call Ext2ReadGroupDesc
-
- // Group descriptor has been read, now
- // grab the inode table block number from it
- push HEX(7000)
- pop es
- mov di, HEX(8008)
- pop eax // Restore inode offset block number from stack
- add eax, es:[di] // Add the inode table start block
-
- // Adjust the read offset so that the
- // inode we want is read to 6000:8000
- pop edx // Restore inode offset in the block from stack
- mov ebx, HEX(68000)
- sub ebx,edx
- shr ebx,4
- mov es,bx
- xor bx,bx
-
- call Ext2ReadBlock
- ret
-
-
-// Reads logical sectors into ES:[BX]
-// EAX has logical sector number to read
-// CX has number of sectors to read
-ReadSectors:
- add eax, dword ptr [bp+Ext2VolumeStartSector] // Add the start of the volume
- cmp eax, [bp-BIOS_CHS_DRIVE_SIZE] // Check if they are reading a sector outside CHS range
- jae ReadSectorsLBA // Yes - go to the LBA routine
- // If at all possible we want to use LBA routines because
- // They are optimized to read more than 1 sector per read
-
- pushad // Save logical sector number & sector count
-
-CheckInt13hExtensions: // Now check if this computer supports extended reads
- mov ah, HEX(41) // AH = 41h
- mov bx, HEX(55aa) // BX = 55AAh
- mov dl, byte ptr [bp+BootDrive] // DL = drive (80h-FFh)
- int HEX(13) // IBM/MS INT 13 Extensions - INSTALLATION CHECK
- jc ReadSectorsCHS // CF set on error (extensions not supported)
- cmp bx, HEX(0aa55) // BX = AA55h if installed
- jne ReadSectorsCHS
- test cl,1 // CX = API subset support bitmap
- jz ReadSectorsCHS // Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
-
- popad // Restore sector count & logical sector number
-
-ReadSectorsLBA:
- pushad // Save logical sector number & sector count
-
- cmp cx, 64 // Since the LBA calls only support 0x7F sectors at a time we will limit ourselves to 64
- jbe ReadSectorsSetupDiskAddressPacket // If we are reading less than 65 sectors then just do the read
- mov cx,64 // Otherwise read only 64 sectors on this loop iteration
-
-ReadSectorsSetupDiskAddressPacket:
- mov [bp-LBA_SECTORS_READ],cx
- mov word ptr [bp-LBA_SECTORS_READ+2],0
- data32 push 0
- push eax // Put 64-bit logical block address on stack
- push es // Put transfer segment on stack
- push bx // Put transfer offset on stack
- push cx // Set transfer count
- push 16 // Set size of packet to 10h
- mov si,sp // Setup disk address packet on stack
-
-
- mov dl, byte ptr [bp+BootDrive] // Drive number
- mov ah, HEX(42) // Int 13h, AH = 42h - Extended Read
- int HEX(13) // Call BIOS
- jc PrintDiskError // If the read failed then abort
-
- add sp, 16 // Remove disk address packet from stack
-
- popad // Restore sector count & logical sector number
-
- push bx
- mov ebx, [bp-LBA_SECTORS_READ]
- add eax,ebx // Increment sector to read
- shl ebx,5
- mov dx,es
- add dx,bx // Setup read buffer for next sector
- mov es,dx
- pop bx
-
- sub cx,[bp-LBA_SECTORS_READ]
- jnz ReadSectorsLBA // Read next sector
-
- ret
-
-
-// Reads logical sectors into ES:[BX]
-// EAX has logical sector number to read
-// CX has number of sectors to read
-ReadSectorsCHS:
- popad // Get logical sector number & sector count off stack
-
-ReadSectorsCHSLoop:
- pushad
- xor edx,edx
- mov ecx, [bp-SECTORS_PER_TRACK]
- div ecx // Divide logical by SectorsPerTrack
- inc dl // Sectors numbering starts at 1 not 0
- mov cl,dl // Sector in CL
- mov edx,eax
- shr edx,16
- div word ptr [bp-NUMBER_OF_HEADS] // Divide logical by number of heads
- mov dh,dl // Head in DH
- mov dl, byte ptr [bp+BootDrive] // Drive number in DL
- mov ch,al // Cylinder in CX
- ror ah,2 // Low 8 bits of cylinder in CH, high 2 bits
- // in CL shifted to bits 6 & 7
- or cl,ah // Or with sector number
- mov ax, HEX(0201)
- int HEX(13) // DISK - READ SECTORS INTO MEMORY
- // AL = number of sectors to read, CH = track, CL = sector
- // DH = head, DL = drive, ES:BX -> buffer to fill
- // Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
-
- jc PrintDiskError // If the read failed then abort
-
- popad
-
- inc eax // Increment Sector to Read
-
- mov dx,es
- add dx, HEX(20) // Increment read buffer for next sector
- mov es,dx
-
- loop ReadSectorsCHSLoop // Read next sector
-
- ret
-
-
-
-
-// Displays a disk error message
-// And reboots
-PrintDiskError:
- mov si,msgDiskError // Bad boot disk message
- call PutChars // Display it
-
-Reboot:
- mov si,msgAnyKey // Press any key message
- call PutChars // Display it
- xor ax,ax
- int HEX(16) // Wait for a keypress
- int HEX(19) // Reboot
-
-PutChars:
- lodsb
- or al,al
- jz short Done
- call PutCharsCallBios
- jmp short PutChars
-PutCharsCallBios:
- mov ah, HEX(0e)
- mov bx, HEX(07)
- int HEX(10)
- ret
-Done:
- mov al, HEX(0d)
- call PutCharsCallBios
- mov al, HEX(0a)
- call PutCharsCallBios
- ret
-
-
-
-msgDiskError:
- .ascii "Disk error", NUL
-// Sorry, need the space...
-//msgAnyKey db 'Press any key to restart',0
-msgAnyKey:
- .ascii "Press key", NUL
-
-// times 509-($-$$) db 0 // Pad to 509 bytes
- .org 509
-
-BootPartition:
- .byte 0
-
- .word HEX(0aa55) // BootSector signature
-
-
-// End of bootsector
-//
-// Now starts the extra boot code that we will store
-// at sector 1 on a EXT2 volume
-
-
-
-LoadRootDirectory:
-
- mov eax,EXT2_ROOT_INO // Put the root directory inode number in EAX
- call Ext2ReadInode // Read in the inode
-
- // Point ES:DI to the inode structure at 6000:8000
- push HEX(6000)
- pop es
- mov di, HEX(8000)
- push di
- push es // Save these for later
-
- // Get root directory size from inode structure
- mov eax, es:[di+4]
- push eax
-
- // Now that the inode has been read in load
- // the root directory file data to 0000:8000
- call Ext2ReadEntireFile
-
- // Since the root directory was loaded to 0000:8000
- // then add 8000h to the root directory's size
- pop eax
- mov edx, HEX(8000) // Set EDX to the current offset in the root directory
- add eax,edx // Initially add 8000h to the size of the root directory
-
-SearchRootDirectory:
- push edx // Save current offset in root directory
- push eax // Save the size of the root directory
-
- // Now we have to convert the current offset
- // in the root directory to a SEGMENT:OFFSET pair
- mov eax,edx
- xor edx,edx
- mov ecx,16
- div ecx // Now AX:DX has segment & offset
- mov es,ax
- mov di,dx
- push di // Save the start of the directory entry
- add di, 8 // Add the offset to the filename
- mov si,filename
- mov cl,11
- repe cmpsb // Compare the file names
- pop di
- pop eax
- pop edx
- jz FoundFile
-
- // Nope, didn't find it in this entry, keep looking
- movzx ecx,word ptr es:[di+4]
- add edx,ecx
-
- // Check to see if we have reached the
- // end of the root directory
- cmp edx,eax
- jb SearchRootDirectory
- jmp PrintFileNotFound
-
-FoundFile:
- mov eax,es:[di] // Get inode number from directory entry
- call Ext2ReadInode // Read in the inode
-
- // Point ES:DI to the inode structure at 6000:8000
- pop es
- pop di // These were saved earlier
-
- mov cx, es:[di] // Get the file mode so we can make sure it's a regular file
- and ch,EXT2_S_IFMT // Mask off everything but the file type
- cmp ch,EXT2_S_IFREG // Make sure it's a regular file
- je LoadFreeLoader
- jmp PrintRegFileError
-
-LoadFreeLoader:
- mov si,msgLoading // "Loading FreeLoader..." message
- call PutChars // Display it
-
- call Ext2ReadEntireFile // Read freeldr.sys to 0000:8000
-
- mov dl, byte ptr [bp+BootDrive]
- mov dh, byte ptr [bp+BootPartition]
- push 0 // push segment (0x0000)
- mov eax, [HEX(8000) + HEX(0A8)] // load the RVA of the EntryPoint into eax
- add eax, HEX(8000) // RVA -> VA
- push ax // push offset
- retf // Transfer control to FreeLoader
-
-
-
-
-
-// Reads ext2 file data into [0000:8000]
-// This function assumes that the file's
-// inode has been read in to 6000:8000 *and*
-// ES:DI points to 6000:8000
-// This will load all the blocks up to
-// and including the double-indirect pointers.
-// This should be sufficient because it
-// allows for ~64MB which is much bigger
-// than we need for a boot loader.
-Ext2ReadEntireFile:
-
- // Reset the load segment
- mov word ptr [bp+Ext2ReadEntireFileLoadSegment], HEX(800)
-
- // Now we must calculate how
- // many blocks to read in
- // We will do this by rounding the
- // file size up to the next block
- // size and then dividing by the block size
- mov eax, dword ptr [bp+Ext2BlockSizeInBytes] // Get the block size in bytes
- push eax
- dec eax // Ext2BlockSizeInBytes -= 1
- add eax, es:[di+4] // Add the file size
- xor edx,edx
- pop ecx // Divide by the block size in bytes
- div ecx // EAX now contains the number of blocks to load
- push eax
-
- // Make sure the file size isn't zero
- cmp eax, 0
- jnz Ext2ReadEntireFile2
- jmp PrintFileSizeError
-
-Ext2ReadEntireFile2:
- // Save the indirect & double indirect pointers
- mov edx, es:[di+ HEX(58)] // Get indirect pointer
- mov dword ptr [bp+Ext2InodeIndirectPointer], edx // Save indirect pointer
- mov edx, es:[di+ HEX(5c)] // Get double indirect pointer
- mov dword ptr [bp+Ext2InodeDoubleIndirectPointer],edx // Save double indirect pointer
-
- // Now copy the direct pointers to 7000:0000
- // so that we can call Ext2ReadDirectBlocks
- push ds // Save DS
- push es
- push HEX(7000)
- pop es
- pop ds
- mov si, HEX(8028)
- xor di,di // DS:SI = 6000:8028 ES:DI = 7000:0000
- mov cx,24 // Moving 24 words of data
- rep movsw
- pop ds // Restore DS
-
- // Now we have all the block pointers in the
- // right location so read them in
- pop eax // Restore the total number of blocks in this file
- xor ecx,ecx // Set the max count of blocks to read to 12
- mov cl,12 // which is the number of direct block pointers in the inode
- call Ext2ReadDirectBlockList
-
- // Check to see if we actually have
- // blocks left to read
- cmp eax, 0
- jz Ext2ReadEntireFileDone
-
- // Now we have read all the direct blocks in
- // the inode. So now we have to read the indirect
- // block and read all it's direct blocks
- push eax // Save the total block count
- mov eax, dword ptr [bp+Ext2InodeIndirectPointer] // Get the indirect block pointer
- push HEX(7000)
- pop es
- xor bx,bx // Set the load address to 7000:0000
- call Ext2ReadBlock // Read the block
-
- // Now we have all the block pointers from the
- // indirect block in the right location so read them in
- pop eax // Restore the total block count
- mov ecx, dword ptr [bp+Ext2PointersPerBlock] // Get the number of block pointers that one block contains
- call Ext2ReadDirectBlockList
-
- // Check to see if we actually have
- // blocks left to read
- cmp eax, 0
- jz Ext2ReadEntireFileDone
-
- // Now we have read all the direct blocks from
- // the inode's indirect block pointer. So now
- // we have to read the double indirect block
- // and read all it's indirect blocks
- // (whew, it's a good thing I don't support triple indirect blocks)
- mov dword ptr [bp+Ext2BlocksLeftToRead],eax // Save the total block count
- mov eax, dword ptr [bp+Ext2InodeDoubleIndirectPointer] // Get the double indirect block pointer
- push HEX(7800)
- pop es
- push es // Save an extra copy of this value on the stack
- xor bx,bx // Set the load address to 7000:8000
- call Ext2ReadBlock // Read the block
-
- pop es // Put 7800h into ES (saved on the stack already)
- xor di,di
-
-Ext2ReadIndirectBlock:
- mov eax, es:[di] // Get indirect block pointer
- add di, 4 // Update DI for next array index
- push es
- push di
-
- push HEX(7000)
- pop es
- xor bx,bx // Set the load address to 7000:0000
- call Ext2ReadBlock // Read the indirect block
-
- // Now we have all the block pointers from the
- // indirect block in the right location so read them in
- mov eax, dword ptr [bp+Ext2BlocksLeftToRead] // Restore the total block count
- mov ecx, dword ptr [bp+Ext2PointersPerBlock] // Get the number of block pointers that one block contains
- call Ext2ReadDirectBlockList
- mov dword ptr [bp+Ext2BlocksLeftToRead],eax // Save the total block count
- pop di
- pop es
-
- // Check to see if we actually have
- // blocks left to read
- cmp eax, 0
- jnz Ext2ReadIndirectBlock
-
-Ext2ReadEntireFileDone:
- ret
-
-// Reads a maximum number of blocks
-// from an array at 7000:0000
-// and updates the total count
-// ECX contains the max number of blocks to read
-// EAX contains the number of blocks left to read
-// On return:
-// EAX contains the new number of blocks left to read
-Ext2ReadDirectBlockList:
- cmp eax,ecx // Compare it to the maximum number of blocks to read
- ja CallExt2ReadDirectBlocks // If it will take more blocks then just read all of the blocks
- mov cx,ax // Otherwise adjust the block count accordingly
-
-CallExt2ReadDirectBlocks:
- sub eax,ecx // Subtract the number of blocks being read from the total count
- push eax // Save the new total count
- call Ext2ReadDirectBlocks
- pop eax // Restore the total count
- ret
-
-
-// Reads a specified number of blocks
-// from an array at 7000:0000
-// CX contains the number of blocks to read
-Ext2ReadDirectBlocks:
-
- push HEX(7000)
- pop es
- xor di,di // Set ES:DI = 7000:0000
-
-Ext2ReadDirectBlocksLoop:
- mov eax,es:[di] // Get direct block pointer from array
- add di, 4 // Update DI for next array index
-
- push cx // Save number of direct blocks left
- push es // Save array segment
- push di // Save array offset
- mov es,[bp+Ext2ReadEntireFileLoadSegment]
- xor bx,bx // Setup load address for next read
-
- call Ext2ReadBlock // Read the block (this updates ES for the next read)
-
- mov [bp+Ext2ReadEntireFileLoadSegment],es // Save updated ES
-
- pop di // Restore the array offset
- pop es // Restore the array segment
- pop cx // Restore the number of blocks left
-
- loop Ext2ReadDirectBlocksLoop
-
- // At this point all the direct blocks should
- // be loaded and ES (Ext2ReadEntireFileLoadSegment)
- // should be ready for the next read.
- ret
-
-
-
-// Displays a file not found error message
-// And reboots
-PrintFileNotFound:
- mov si,msgFreeLdr // FreeLdr not found message
- jmp short DisplayItAndReboot
-
-// Displays a file size is 0 error
-// And reboots
-PrintFileSizeError:
- mov si,msgFileSize // Error message
- jmp short DisplayItAndReboot
-
-// Displays a file is not a regular file error
-// And reboots
-PrintRegFileError:
- mov si,msgRegFile // Error message
-DisplayItAndReboot:
- call PutChars // Display it
- jmp Reboot
-
-msgFreeLdr:
- .ascii "freeldr.sys not found", NUL
-msgFileSize:
- .ascii "File size 0", NUL
-msgRegFile:
- .ascii "freeldr.sys isnt a regular file", NUL
-filename:
- .ascii "freeldr.sys"
-msgLoading:
- .ascii "Loading...", NUL
-
-// times 1022-($-$$) db 0 // Pad to 1022 bytes
-.org 1022
-
- .word HEX(0aa55) // BootSector signature
-
-.endcode16
-
-END
diff --git a/boot/freeldr/bootsect/extldr.S b/boot/freeldr/bootsect/extldr.S
new file mode 100644
index 00000000000..08074831392
--- /dev/null
+++ b/boot/freeldr/bootsect/extldr.S
@@ -0,0 +1,583 @@
+/*
+ * PROJECT: FreeLoader
+ * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE: EXTFS second stage loader
+ * COPYRIGHT: Copyright 2024-2025 Daniel Victor <ilauncherdeveloper(a)gmail.com>
+ */
+
+#define INCLUDED_ASM
+#include "ext.S"
+
+ExtLdrEntryPoint:
+ // Clear segment registers
+ xor eax, eax
+ mov ds, ax
+ mov es, ax
+
+ // Read root directory Inode
+ mov al, EXT_ROOT_INODE
+ call ExtReadInode
+
+ // Set file base address and search for freeldr
+ mov dword ptr BP_REL(ExtFileAddress), FREELDR_BASE
+ call ExtSetFileSegment
+
+ // Swap ES with DS segment and clear SI
+ call SwapESWithDS
+ xor si, si
+
+ // Set the directory entries size limit
+ mov eax, EXT_INODE_DATA_SIZE_LIMIT
+
+ // Get directory entries size
+ mov edx, dword ptr BP_REL(ExtFileSize)
+
+ // Set the buffer size with limit
+ cmp edx, eax
+ jbe .FLoop2
+ mov edx, eax
+.FLoop2:
+ // Load directory Inode
+ mov eax, dword ptr ds:[si]
+
+ // If the buffer reached the end then abort the search
+ cmp si, dx
+ jae FreeLdrPrintFileNotFound
+
+ // Save SI
+ push si
+
+ // If the Inode is zero then skip this entry
+ test eax, eax
+ jz .FSkip2
+
+ mov di, offset FreeLdrFileName // Load target filename address
+ mov cx, offset FreeLdrFileNameEnd - FreeLdrFileName // Length of filename to compare
+ cmp byte ptr ds:[si + EXT_DIRECTORY_ENTRY_NAME_LENGTH_OFFSET], cl // Compare if both names have the same length
+ jnz .FSkip2 // Skip this entry if yes
+ add si, EXT_DIRECTORY_ENTRY_NAME_OFFSET // Move to filename in entry
+ repe cmpsb // Compare filenames
+ pop si // Restore SI
+ jz LoadFreeLdr // Found matching file
+ push si // Save SI
+
+.FSkip2:
+ // Restore SI
+ pop si
+
+ // Move to next directory entry
+ add si, word ptr ds:[si + EXT_DIRECTORY_ENTRY_SIZE_OFFSET]
+
+ jmp .FLoop2
+
+ExtFileIndirectPointer:
+ .long 0
+ExtFileIndirectPointerDouble:
+ .long 0
+
+SwapESWithDS:
+ // Swap ES and DS
+ push es
+ push ds
+ pop es
+ pop ds
+ ret
+
+ExtSetFileSegment:
+ mov ebx, dword ptr BP_REL(ExtFileAddress) // Get the EXT file address
+ shr ebx, 4 // Shift four bits to the right to get segment
+ jmp .ExtSkip
+ExtSetInodeSegment:
+ mov bx, EXT_INODE_ADDRESS / 16 // Get the EXT inode address
+ jmp .ExtSkip
+ExtSetBlockSegment:
+ mov bx, EXT_BLOCK_ADDRESS / 16 // Get the EXT block address
+ jmp .ExtSkip
+ExtSetBlock2Segment:
+ mov bx, EXT_BLOCK2_ADDRESS / 16 // Get the EXT second block address
+ jmp .ExtSkip
+ExtSetBlock3Segment:
+ mov bx, EXT_BLOCK3_ADDRESS / 16 // Get the EXT third block address
+ jmp .ExtSkip
+ExtSetBlock4Segment:
+ mov bx, EXT_BLOCK4_ADDRESS / 16 // Get the EXT fourth block address
+ jmp .ExtSkip
+ExtSetBlock5Segment:
+ mov bx, EXT_BLOCK5_ADDRESS / 16 // Get the EXT fifth block address
+ jmp .ExtSkip
+ExtSetBlock6Segment:
+ mov bx, EXT_BLOCK6_ADDRESS / 16 // Get the EXT sixth block address
+ jmp .ExtSkip
+ExtSetBlock7Segment:
+ mov bx, EXT_BLOCK7_ADDRESS / 16 // Get the EXT seventh block address
+.ExtSkip:
+ mov es, bx // Set ES
+ xor bx, bx // Clear BX
+ ret
+
+ExtUpdateFileSize:
+ mov eax, dword ptr BP_REL(ExtBlockSizeInBytes)
+
+ExtAdjustFileSize:
+ // Update the file size
+ sub dword ptr BP_REL(ExtFileSizeState), eax
+ add dword ptr BP_REL(ExtFileAddress), eax
+ ret
+
+ExtInodeDetectExtentsFlag:
+ push eax
+ mov eax, es:[si + EXT_INODE_FLAGS_OFFSET]
+ test eax, EXT_INODE_FLAG_EXTENTS
+ pop eax
+ ret
+
+ExtFileReadBlocks:
+ // If the block count is zero then do nothing
+ test bx, bx
+ jz .FRDone
+
+ // Read the block
+ call ExtFileReadBlock
+
+ // Go to the next block and decrement the block count
+ inc eax
+ dec bx
+
+ // Loop until all blocks are read
+ jmp ExtFileReadBlocks
+.FRDone:
+ ret
+
+ExtSafeReadBlock:
+ pushad
+
+ // If the block is zero then just clear the block
+ test eax, eax
+ jz .NullBlk
+
+ // Read the block safely
+ call ExtReadBlock
+ jmp .RBDone
+.NullBlk:
+ // If the block is 0 then just clear the block
+ mov di, bx
+ xor ax, ax
+ mov cx, word ptr BP_REL(ExtBlockSizeInBytes)
+ rep stosb
+.RBDone:
+ popad
+ ret
+
+// Reads a block from the EXT file
+// EAX has the block to read
+// ExtFileAddress has the address to write to
+ExtFileReadBlock:
+ push es
+ pushad
+
+ // Set the EXT file segment
+ call ExtSetFileSegment
+
+ // Read the block safely
+ call ExtSafeReadBlock
+
+ // Update the file size
+ call ExtUpdateFileSize
+
+ // Exit
+ popad
+ pop es
+ ret
+
+ExtReadEntireFileDone:
+ push eax // Save EAX register
+ mov eax, dword ptr BP_REL(ExtBlockSizeInBytes) // Load block size in bytes into EAX
+ cmp dword ptr BP_REL(ExtFileSizeState), eax // Compare file size state with block size
+ pop eax // Restore EAX register
+ ret // Return from procedure
+
+// Loops over the block pointers and reads the blocks
+// until the file size state is zero
+ExtReadEntireFileLoop:
+ call ExtReadEntireFileDone
+ jb .RDone
+
+ mov eax, dword ptr es:[si]
+
+ // Read the block safely
+ call ExtFileReadBlock
+
+ add si, EXT_POINTER_SIZE
+ loop ExtReadEntireFileLoop
+.RDone:
+ ret
+
+// Reads the double indirect block data
+// This function is used to read the blocks that are not contiguous
+// to the blocks that are pointed by the indirect block
+ExtReadEntireFileIndirectDouble:
+ push es
+ pushad
+
+ // Check if there is no more blocks to read
+ call ExtReadEntireFileDone
+ jb .RDone4
+
+ // Reset block offset
+ xor si, si
+
+ // Load the double indirect block address
+ mov eax, dword ptr BP_REL(ExtFileIndirectPointerDouble)
+ call ExtSetBlock2Segment
+ call ExtSafeReadBlock
+
+ // Load the number of pointers per block
+ mov ecx, dword ptr BP_REL(ExtPointersPerBlock)
+.RLoop4:
+ // Check if there is no more blocks to read
+ call ExtReadEntireFileDone
+ jb .RDone4
+
+ // Get the block address
+ mov eax, dword ptr es:[si]
+
+ // Read the indirect block
+ call ExtReadEntireFileIndirect
+
+ // Increment block offset
+ add si, EXT_POINTER_SIZE
+
+ // Loop until all blocks are read
+ loop .RLoop4
+.RDone4:
+ popad
+ pop es
+ ret
+
+// Reads the indirect block data
+ExtReadEntireFileIndirect:
+ push es
+ pushad
+
+ // Check if there is no more blocks to read
+ call ExtReadEntireFileDone
+ jb .RDone3
+
+ // Reset block offset
+ xor si, si
+
+ // Set the block segment
+ call ExtSetBlockSegment
+
+ // Read the block safely
+ call ExtSafeReadBlock
+
+ // Read the blocks
+ mov ecx, dword ptr BP_REL(ExtPointersPerBlock)
+ call ExtReadEntireFileLoop
+
+.RDone3:
+ popad
+ pop es
+ ret
+
+// Reads the direct block data
+ExtReadEntireFileDirect:
+ push es
+ pushad
+
+ // If there is no more blocks to read then abort it
+ call ExtReadEntireFileDone
+ jb .RDone2
+
+ // Move to block pointer in Inode
+ add si, EXT_INODE_BLOCK_POINTER_OFFSET
+ xor ecx, ecx
+ mov cl, EXT_INODE_BLOCKS
+
+ // Set the correct segment
+ call ExtSetInodeSegment
+
+ // Read the blocks
+ call ExtReadEntireFileLoop
+
+.RDone2:
+ popad
+ pop es
+ ret
+
+ExtExtentsLevelSegmentFunctionTable:
+ .word ExtSetBlockSegment
+ .word ExtSetBlock2Segment
+ .word ExtSetBlock3Segment
+ .word ExtSetBlock4Segment
+ .word ExtSetBlock5Segment
+ .word ExtSetBlock6Segment
+
+ExtExtentsLevelFunctionTable:
+ .word ExtReadEntireFileExtentsLevel0
+ .word ExtReadEntireFileExtentsLevelX
+ .word ExtReadEntireFileExtentsLevelX
+ .word ExtReadEntireFileExtentsLevelX
+ .word ExtReadEntireFileExtentsLevelX
+ .word ExtReadEntireFileExtentsLevelX
+
+ExtReadEntireFileExtentsLevelX:
+ push es
+ pushad
+
+ // Load extent header entries
+ mov cx, word ptr es:[si + EXT_EXTENT_HEADER_ENTRIES_OFFSET]
+.ExtentsLoopX:
+ // Check if there is no more blocks to read
+ call ExtReadEntireFileDone
+ jb .ExtentsDoneX
+
+ // Go to next extent
+ add si, EXT_EXTENT_SIZE
+
+ // Save current state
+ push es
+ pushad
+
+ // Read the extent block
+ mov eax, dword ptr es:[si + EXT_EXTENT_INDEX_LEAF_OFFSET]
+
+ // Set block segment and read block safely
+ call ExtSetBlock7Segment
+ call ExtSafeReadBlock
+
+ // Reset SI for calculations
+ xor si, si
+
+ // Calculate function table offset
+ mov bp, word ptr es:[si + EXT_EXTENT_HEADER_DEPTH_OFFSET]
+ shl bp, 1
+
+ // Call the segment and level functions
+ call word ptr cs:ExtExtentsLevelSegmentFunctionTable[bp]
+ call ExtSafeReadBlock
+ call word ptr cs:ExtExtentsLevelFunctionTable[bp]
+
+ // Restore state and continue loop
+ popad
+ pop es
+
+ loop .ExtentsLoopX
+.ExtentsDoneX:
+ popad
+ pop es
+ ret
+
+ExtReadEntireFileExtentsLevel0:
+ push es
+ pushad
+
+ // Load extent header entries
+ mov cx, word ptr es:[si + EXT_EXTENT_HEADER_ENTRIES_OFFSET]
+
+.ExtentsLoop0:
+ // Check if there is no more blocks to read
+ call ExtReadEntireFileDone
+ jb .ExtentsDone0
+
+ // Go to next extent
+ add si, EXT_EXTENT_SIZE
+
+ // Load extent length
+ mov bx, word ptr es:[si + EXT_EXTENT_LENGTH_OFFSET]
+ and ebx, HEX(FFFF)
+
+ // Check if extent is sparse
+ cmp bx, EXT_EXTENT_MAX_LENGTH
+ jbe .NotSparse
+
+ // Adjust sparse extent length
+ sub bx, EXT_EXTENT_MAX_LENGTH
+
+ push es
+.SparseLoop:
+ // Check if the sparse blocks reached the end
+ test bx, bx
+ jz .SparseDone
+
+ xor eax, eax
+ call ExtFileReadBlock
+
+ // Decrement the block count
+ dec bx
+ jmp .SparseLoop
+.SparseDone:
+ pop es
+ jmp .ExtentsSkip0
+
+.NotSparse:
+ // Read blocks from extent start
+ mov eax, dword ptr es:[si + EXT_EXTENT_START_OFFSET]
+ call ExtFileReadBlocks
+
+.ExtentsSkip0:
+ loop .ExtentsLoop0
+.ExtentsDone0:
+ popad
+ pop es
+ ret
+
+ExtReadEntireFileExtents:
+ push es
+ pushad
+
+ // Add the extent header offset
+ add si, EXT_INODE_BLOCK_POINTER_OFFSET
+
+ // Load extent header depth
+ mov ax, word ptr es:[si + EXT_EXTENT_HEADER_DEPTH_OFFSET]
+
+ // Check if the file has more than the maximum allowed levels
+ cmp ax, EXT_EXTENT_MAX_LEVEL
+ ja FreeLdrPrintFileBig
+
+ // If the extent header depth is zero then this is a level 0 extent
+ test ax, ax
+ jz .Level0
+
+ // Call the recursive function
+.LevelX:
+ call ExtReadEntireFileExtentsLevelX
+
+ // Jump to the end of the function
+ jmp .FEDone
+
+ // Level 0 extent
+.Level0:
+ // Call the level 0 extent function
+ call ExtReadEntireFileExtentsLevel0
+
+ // End of the function
+.FEDone:
+ popad
+ pop es
+ ret
+
+// Reads the entire file in EXTFS
+ExtReadEntireFile:
+ // Set the correct Inode offset
+ mov si, word ptr BP_REL(ExtReadInodeIndexOffset)
+
+ // Set file size
+ mov ecx, dword ptr es:[si + EXT_INODE_SIZE_OFFSET]
+ mov dword ptr BP_REL(ExtFileSize), ecx
+
+ // If file size is zero then abort it
+ test ecx, ecx
+ jz FreeLdrPrintFileZero
+
+ // Set rounded up file size
+ add ecx, dword ptr BP_REL(ExtBlockSizeInBytes)
+ dec ecx
+ mov dword ptr BP_REL(ExtFileSizeState), ecx
+
+ // Use extents method if necessary
+ call ExtInodeDetectExtentsFlag
+ jz .NoExtents
+
+ // Call the extents method
+ call ExtReadEntireFileExtents
+ ret
+
+.NoExtents:
+ // Set Indirect pointer
+ mov eax, dword ptr es:[si + (EXT_INODE_BLOCK_POINTER_OFFSET + (EXT_INODE_BLOCKS * EXT_POINTER_SIZE))]
+ mov dword ptr BP_REL(ExtFileIndirectPointer), eax
+
+ // Set Double indirect pointer
+ mov eax, dword ptr es:[si + (EXT_INODE_BLOCK_POINTER_OFFSET + (EXT_INODE_BLOCKS * EXT_POINTER_SIZE) + EXT_POINTER_SIZE)]
+ mov dword ptr BP_REL(ExtFileIndirectPointerDouble), eax
+
+ call ExtReadEntireFileDirect // Read the direct blocks
+
+ mov eax, dword ptr BP_REL(ExtFileIndirectPointer) // Load the simple indirect pointer
+ call ExtReadEntireFileIndirect // Read the simple indirect blocks
+
+ call ExtReadEntireFileIndirectDouble // Read the double indirect blocks
+ ret
+
+LoadFreeLdr:
+ // Swap ES and DS
+ call SwapESWithDS
+
+ // Show output loading status
+ push si
+ mov si, offset msgLoadingFreeLdr
+ call PutChars
+ pop si
+
+ // Load Inode at directory entry
+ mov eax, dword ptr es:[si]
+ call ExtReadInode
+ mov si, word ptr BP_REL(ExtReadInodeIndexOffset)
+
+ // Get Inode type
+ mov ax, word ptr es:[si]
+ and ax, EXT_INODE_TYPE_MASK
+
+ // If it's not a regular file then abort it
+ cmp ax, EXT_INODE_TYPE_REGULAR
+ jnz FreeLdrPrintRegFileError
+
+ // Load Freeldr at FREELDR_BASE
+ mov dword ptr BP_REL(ExtFileAddress), FREELDR_BASE
+ call ExtReadEntireFile
+
+ // Restore the boot drive and partition
+ mov dl, byte ptr BP_REL(BootDrive)
+ mov dh, byte ptr BP_REL(BootPartition)
+
+ // Transfer execution to the bootloader
+ ljmp16 FREELDR_BASE / 16, 0
+
+FreeLdrPrintFileBig:
+ // Make DS correct, display it and reboot
+ call SwapESWithDS
+ mov si, offset msgFreeLdrBig
+ jmp DisplayItAndReboot
+
+FreeLdrPrintFileZero:
+ // Make DS correct, display it and reboot
+ call SwapESWithDS
+ mov si, offset msgFreeLdrZero
+ jmp DisplayItAndReboot
+
+FreeLdrPrintFileNotFound:
+ // Make DS correct, display it and reboot
+ call SwapESWithDS
+ mov si, offset msgFreeLdr
+ jmp DisplayItAndReboot
+
+FreeLdrPrintRegFileError:
+ // Make DS correct, display it and reboot
+ call SwapESWithDS
+ mov si, offset msgFreeLdrNotRegularFile // FreeLdr not found message
+ jmp DisplayItAndReboot
+
+FreeLdrFileName:
+ .ascii "freeldr.sys"
+FreeLdrFileNameEnd:
+
+msgFreeLdrZero:
+ .ascii "freeldr.sys size is zero", CR, LF, NUL
+msgFreeLdrBig:
+ .ascii "freeldr.sys has many extent levels", CR, LF, NUL
+msgFreeLdr:
+ .ascii "freeldr.sys not found", CR, LF, NUL
+msgFreeLdrNotRegularFile:
+ .ascii "freeldr.sys is not a regular file", CR, LF, NUL
+msgLoadingFreeLdr:
+ .ascii "Loading FreeLoader...", CR, LF, NUL
+
+.org (EXTLDR_BOOTSECTOR_SIZE - 2)
+.word HEX(AA55) // BootSector signature
+
+.endcode16
+
+END
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=9da45923b33fba22a509c…
commit 9da45923b33fba22a509c45df7f78f870bd98fb6
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Sat Mar 8 21:18:37 2025 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Tue Mar 18 21:20:32 2025 +0100
[CONFIGURE] Adjust some echo'ed strings (#7773)
[CONFIGURE.CMD] Use multi-command syntax instead of AND operator for successive echo's
And adjust few strings.
[CONFIGURE.SH] Quote the echo'ed strings, and adjust some of them.
---
configure.cmd | 24 +++++++++++-------------
configure.sh | 12 ++++++------
2 files changed, 17 insertions(+), 19 deletions(-)
diff --git a/configure.cmd b/configure.cmd
index d94501ab4bc..c0c318e8756 100755
--- a/configure.cmd
+++ b/configure.cmd
@@ -24,7 +24,7 @@ set REACTOS_SOURCE_DIR=%~dp0
REM Ensure there's no spaces in the source path
echo %REACTOS_SOURCE_DIR%| find " " > NUL
if %ERRORLEVEL% == 0 (
- echo. && echo Your source path contains at least one space.
+ echo. & echo Your source path contains at least one space.
echo This will cause problems with building.
echo Please rename your folders so there are no spaces in the source path,
echo or move your source to a different folder.
@@ -97,14 +97,14 @@ set REMAINING=%*
) else if /I "!PARAM!" == "Ninja" (
set CMAKE_GENERATOR="Ninja"
) else if /I "!PARAM!" == "VSSolution" (
- echo. && echo Error: Creation of VS Solution files is not supported in a MinGW environment.
+ echo. & echo Error: Creation of VS Solution files is not supported in a MinGW environment.
echo Please run this command in a [Developer] Command Prompt for Visual Studio.
goto quit
) else if /I "!PARAM:~0,2!" == "-D" (
REM User is passing a switch to CMake
set "CMAKE_PARAMS=%CMAKE_PARAMS% !PARAM!"
) else (
- echo. && echo Warning: Unrecognized switch "!PARAM!" && echo.
+ echo. & echo Warning: Unrecognized switch "!PARAM!" & echo.
)
) else (
if /I "!PARAM!" == "CodeBlocks" (
@@ -145,7 +145,7 @@ set REMAINING=%*
REM User is passing a switch to CMake
set "CMAKE_PARAMS=%CMAKE_PARAMS% !PARAM!"
) else (
- echo. && echo Warning: Unrecognized switch "!PARAM!" && echo.
+ echo. & echo Warning: Unrecognized switch "!PARAM!" & echo.
)
)
@@ -175,17 +175,16 @@ if "%REACTOS_SOURCE_DIR%" == "%CD%\" (
)
if "%VS_SOLUTION%" == "1" (
-
if exist build.ninja (
- echo. && echo Error: This directory has already been configured for ninja.
+ echo. & echo Error: This directory has already been configured for ninja.
echo An output folder configured for ninja can't be reconfigured for VSSolution.
echo Use an empty folder or delete the contents of this folder, then try again.
goto quit
)
) else if exist REACTOS.sln (
- echo. && echo Error: This directory has already been configured for Visual Studio.
+ echo. & echo Error: This directory has already been configured for Visual Studio.
echo An output folder configured for VSSolution can't be reconfigured for ninja.
- echo Use an empty folder or delete the contents of this folder, then try again. && echo.
+ echo Use an empty folder or delete the contents of this folder, then try again. & echo.
goto quit
)
@@ -195,7 +194,6 @@ if EXIST CMakeCache.txt (
del CMakeCache.txt /q
)
-
if "%BUILD_ENVIRONMENT%" == "MinGW" (
cmake -G %CMAKE_GENERATOR% -DENABLE_CCACHE:BOOL=0 -DCMAKE_TOOLCHAIN_FILE:FILEPATH=%MINGW_TOOCHAIN_FILE% -DARCH:STRING=%ARCH% %BUILD_TOOLS_FLAG% %CMAKE_PARAMS% "%REACTOS_SOURCE_DIR%"
) else if %USE_CLANG_CL% == 1 (
@@ -213,17 +211,17 @@ if "%CD_SAME_AS_SOURCE%" == "1" (
)
if "%VS_SOLUTION%" == "1" (
- set ENDV= You can now use msbuild or open REACTOS.sln%ENDV%.
+ set ENDV= You can now use msbuild or open REACTOS.sln%ENDV%
) else (
- set ENDV= Execute appropriate build commands ^(ex: ninja, make, nmake, etc...^)%ENDV%
+ set ENDV= Execute appropriate build commands ^(e.g. ninja, make, nmake, etc.^)%ENDV%
)
-echo. && echo Configure script complete^^!%ENDV%
+echo. & echo Configure script complete^^!%ENDV%
goto quit
:cmake_notfound
-echo Unable to find cmake, if it is installed, check your PATH variable.
+echo Unable to find cmake. If it is installed, check your PATH variable.
:quit
endlocal
diff --git a/configure.sh b/configure.sh
index f9c4679ad13..7a693949d35 100755
--- a/configure.sh
+++ b/configure.sh
@@ -1,7 +1,7 @@
#!/bin/sh
if [ "x$ROS_ARCH" = "x" ]; then
- echo Could not detect RosBE.
+ echo "Could not detect RosBE."
exit 1
fi
@@ -11,7 +11,7 @@ REACTOS_SOURCE_DIR=$(cd `dirname $0` && pwd)
REACTOS_OUTPUT_PATH=output-$BUILD_ENVIRONMENT-$ARCH
usage() {
- echo Invalid parameter given.
+ echo "Invalid parameter given."
exit 1
}
@@ -41,18 +41,18 @@ while [ $# -gt 0 ]; do
done
if [ "$REACTOS_SOURCE_DIR" = "$PWD" ]; then
- echo Creating directories in $REACTOS_OUTPUT_PATH
+ echo "Creating directories in $REACTOS_OUTPUT_PATH"
mkdir -p "$REACTOS_OUTPUT_PATH"
cd "$REACTOS_OUTPUT_PATH"
fi
-echo Preparing reactos...
+echo "Preparing reactos..."
rm -f CMakeCache.txt host-tools/CMakeCache.txt
cmake -G "$CMAKE_GENERATOR" -DENABLE_CCACHE:BOOL=0 -DCMAKE_TOOLCHAIN_FILE:FILEPATH=toolchain-gcc.cmake -DARCH:STRING=$ARCH $EXTRA_ARGS $ROS_CMAKEOPTS "$REACTOS_SOURCE_DIR"
if [ $? -ne 0 ]; then
- echo "An error occured while configuring ReactOS"
+ echo "An error occurred while configuring ReactOS"
exit 1
fi
-echo Configure script complete! Enter directories and execute appropriate build commands \(ex: ninja, make, makex, etc...\).
+echo "Configure script complete! Execute appropriate build commands (e.g. ninja, make, makex, etc.) from $REACTOS_OUTPUT_PATH"
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=57fa5a22defb8711f8efd…
commit 57fa5a22defb8711f8efd2441bffdd6ac8015db3
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Sat Mar 8 21:01:50 2025 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Tue Mar 18 20:17:40 2025 +0100
[GIT] Ensure .sh script files use LF (Unix) line endings (#7772)
For example, this is what's expected by Cygwin (ba)sh on Windows.
---
.gitattributes | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.gitattributes b/.gitattributes
index ee079a75c8d..c2c723297f4 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -30,6 +30,9 @@
*.TXT text
*.y text
+# Files with these extensions must always have LF (Unix) line endings.
+*.sh text eol=lf
+
# Files with these extensions end up in the built ReactOS system, so they
# need to have CRLF line endings.
*.bat text eol=crlf