Reactos
at master 726 lines 24 kB view raw
1/* 2 * PROJECT: FreeLoader 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: EXTFS volume boot sector 5 * COPYRIGHT: Copyright 2002-2003 Brian Palmer <brianp@sginet.com> 6 * Copyright 2024-2025 Daniel Victor <ilauncherdeveloper@gmail.com> 7 */ 8 9#include <asm.inc> 10#include <freeldr/include/arch/pc/x86common.h> 11 12// Boot sector constants 13#define BOOTSECTOR_BASE_ADDRESS HEX(7C00) 14#define EXTLDR_BOOTSECTOR_SIZE 1024 15#define EXT_POINTER_SIZE 4 16#define EXT_EXTENT_SIZE 12 17 18// Maximum extent values 19#define EXT_EXTENT_MAX_LEVEL 5 20#define EXT_EXTENT_MAX_LENGTH 32768 21 22// Group descriptor offsets 23#define EXT_GROUP_DESC_INODE_TABLE_OFFSET 8 24 25// Extent offsets 26#define EXT_EXTENT_HEADER_ENTRIES_OFFSET 2 27#define EXT_EXTENT_HEADER_DEPTH_OFFSET 6 28#define EXT_EXTENT_INDEX_LEAF_OFFSET 4 29#define EXT_EXTENT_LENGTH_OFFSET 4 30#define EXT_EXTENT_START_OFFSET 8 31 32// Inode offsets 33#define EXT_INODE_SIZE_OFFSET 4 34#define EXT_INODE_FLAGS_OFFSET 32 35#define EXT_INODE_BLOCK_POINTER_OFFSET 40 36 37// Directory entry offsets 38#define EXT_DIRECTORY_ENTRY_SIZE_OFFSET 4 39#define EXT_DIRECTORY_ENTRY_NAME_LENGTH_OFFSET 6 40#define EXT_DIRECTORY_ENTRY_NAME_OFFSET 8 41 42// Inode flags 43#define EXT_INODE_FLAG_EXTENTS HEX(80000) 44 45// Inode blocks constants 46#define EXT_INODE_BLOCKS 12 47#define EXT_INODE_INDIRECT_BLOCKS 3 48 49// Root Inode 50#define EXT_ROOT_INODE 2 51 52// Inode address 53#define EXT_INODE_ADDRESS HEX(9000) 54 55// Data block addresses 56#define EXT_BLOCK_ADDRESS HEX(1000) 57#define EXT_BLOCK2_ADDRESS HEX(2000) 58#define EXT_BLOCK3_ADDRESS HEX(3000) 59#define EXT_BLOCK4_ADDRESS HEX(4000) 60#define EXT_BLOCK5_ADDRESS HEX(5000) 61#define EXT_BLOCK6_ADDRESS HEX(6000) 62#define EXT_BLOCK7_ADDRESS HEX(A000) 63 64// Inode types 65#define EXT_INODE_TYPE_MASK HEX(F000) 66#define EXT_INODE_TYPE_REGULAR HEX(8000) 67 68// File size limit 69#define EXT_INODE_DATA_SIZE_LIMIT HEX(F000) 70 71// Offset of functions addresses that will be used by the extldr.sys 3rd-stage bootsector 72#define ExtReadBlockOffset 2 73#define ExtReadInodeOffset 4 74#define DisplayItAndRebootOffset 6 75#define PutCharsOffset 8 76 77// Boot sector stack constants 78#define BOOTSECTOR_STACK_TEMP_VARIABLES 2 79#define BOOTSECTOR_STACK_TEMP_VARIABLES_SIZE (4 * BOOTSECTOR_STACK_TEMP_VARIABLES) 80#define BOOTSECTOR_STACK_OFFSET (8 + BOOTSECTOR_STACK_TEMP_VARIABLES_SIZE) 81#define BOOTSECTOR_STACK_BASE (BOOTSECTOR_BASE_ADDRESS - BOOTSECTOR_STACK_OFFSET) 82#define BP_REL(x) ss:[bp + (x - BOOTSECTOR_BASE_ADDRESS)] 83 84// Temporary variables 85#define ExtFileSizeState ((BOOTSECTOR_STACK_BASE + BOOTSECTOR_STACK_TEMP_VARIABLES_SIZE) - 4) 86#define LBASectorsRead (ExtFileSizeState - 4) 87 88.code16 89 90#ifndef INCLUDED_ASM 91 92start: 93 jmp short main 94 nop 95 96// Fields that will be changed by the installer 97BootDrive: 98 .byte HEX(FF) 99ExtVolumeStartSector: 100 .long 263088 // Start sector of the ext2 volume 101ExtBlockSize: 102 .long 2 // Block size in sectors 103ExtBlockSizeInBytes: 104 .long 1024 // Block size in bytes 105ExtPointersPerBlock: 106 .long 256 // Number of block pointers that can be contained in one block 107ExtGroupDescSize: 108 .long 32 // Size of Group Descriptor 109ExtFirstDataBlock: 110 .long 2 // First data block (2 for 1024-byte blocks, 1 for bigger sizes) 111ExtInodeSize: 112 .long 128 // Size of Inode 113ExtInodesPerGroup: 114 .long 2048 // Number of inodes per group 115 116// File variables 117ExtFileSize: 118 .long 0 // File size in bytes 119ExtFileAddress: 120 .long FREELDR_BASE // File address 121ExtFileAddressOld: 122 .long FREELDR_BASE // Old file address 123 124// Inode variables 125ExtReadInodeGroup: 126 .long 0 127ExtReadInodeIndex: 128 .long 0 129ExtReadInodeGroupBlock: 130 .long 0 131ExtReadInodeIndexBlock: 132 .long 0 133ExtReadInodeGroupOffset: 134 .word 0 135ExtReadInodeIndexOffset: 136 .word 0 137 138main: 139 xor ax, ax // Setup segment registers 140 mov ds, ax // Make DS correct 141 mov es, ax // Make ES correct 142 mov ss, ax // Make SS correct 143 mov bp, BOOTSECTOR_BASE_ADDRESS 144 mov sp, bp // Setup a stack 145 sub sp, BOOTSECTOR_STACK_OFFSET 146 147 // Save the function addresses so the helper code knows where to call them 148 mov word ptr ss:[bp-ExtReadBlockOffset], offset ExtReadBlock 149 mov word ptr ss:[bp-ExtReadInodeOffset], offset ExtReadInode 150 mov word ptr ss:[bp-DisplayItAndRebootOffset], offset DisplayItAndReboot 151 mov word ptr ss:[bp-PutCharsOffset], offset PutChars 152 153 mov si, offset BootDrive 154 cmp byte ptr [si], HEX(0ff) // If they have specified a boot drive then use it 155 jne CheckInt13hExtensions 156 157 mov byte ptr [si], dl // Save the boot drive 158 159// Now check if this computer supports extended reads. This boot sector will not work without it. 160CheckInt13hExtensions: 161 mov ah, HEX(41) // AH = 41h 162 mov bx, HEX(55aa) // BX = 55AAh 163 int HEX(13) // IBM/MS INT 13 Extensions - INSTALLATION CHECK 164 jc PrintDiskError // CF set on error (extensions not supported) 165 cmp bx, HEX(aa55) // BX = AA55h if installed 166 jne PrintDiskError 167 test cl, 1 // si = API subset support bitmap 168 jz PrintDiskError // Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported 169 170LoadExtraBootCode: 171 // First we have to load our extra boot code at 172 // sector 1 into memory at [0000:7e00h] 173 xor eax, eax 174 inc eax 175 mov cx, 1 176 xor bx, bx 177 mov es, bx // Read sector to [0000:7e00h] 178 mov bx, HEX(7e00) 179 call ReadSectors 180 181 jmp LoadRootDirectory 182 183// Reads logical sectors into ES:[BX] 184// EAX has logical sector number to read 185// CX has number of sectors to read 186ReadSectors: 187 push es 188 add eax, dword ptr BP_REL(ExtVolumeStartSector) // Add the start of the volume 189 // If at all possible we want to use LBA routines because 190 // they are optimized to read more than 1 sector per read 191 192ReadSectorsLBA: 193 pushad // Save logical sector number & sector count 194 195 cmp cx, 64 // Since the LBA calls only support 0x7F sectors at a time we will limit ourselves to 64 196 jbe ReadSectorsSetupDiskAddressPacket // If we are reading less than 65 sectors then just do the read 197 mov cx, 64 // Otherwise read only 64 sectors on this loop iteration 198 199ReadSectorsSetupDiskAddressPacket: 200 movzx ecx, cx 201 mov dword ptr BP_REL(LBASectorsRead), ecx 202 data32 push 0 203 push eax // Put 64-bit logical block address on stack 204 push es // Put transfer segment on stack 205 push bx // Put transfer offset on stack 206 push cx // Set transfer count 207 push 16 // Set size of packet to 10h 208 mov si, sp // Setup disk address packet on stack 209 210 mov dl, byte ptr BP_REL(BootDrive) // Drive number 211 mov ah, HEX(42) // Int 13h, AH = 42h - Extended Read 212 int HEX(13) // Call BIOS 213 jc PrintDiskError // If the read failed then abort 214 215 add sp, 16 // Remove disk address packet from stack 216 217 popad // Restore sector count & logical sector number 218 219 push bx 220 mov ebx, dword ptr BP_REL(LBASectorsRead) 221 add eax, ebx // Increment sector to read 222 shl ebx, 5 223 mov dx, es 224 add dx, bx // Setup read buffer for next sector 225 mov es, dx 226 pop bx 227 228 sub cx, word ptr BP_REL(LBASectorsRead) 229 jnz ReadSectorsLBA // Read next sector 230 231 pop es 232 ret 233 234// Displays a disk error message 235// And reboots 236PrintDiskError: 237 mov si, offset msgDiskError // Bad boot disk message 238 call PutChars // Display it 239 240Reboot: 241 mov si, offset msgAnyKey // Press any key message 242 call PutChars // Display it 243 xor ax, ax 244 int HEX(16) // Wait for a keypress 245 int HEX(19) // Reboot 246 247.PutCharsLoop: 248 mov ah, HEX(0E) 249 mov bx, 7 250 int HEX(10) 251PutChars: 252 lodsb 253 or al, al 254 jnz .PutCharsLoop 255 ret 256 257SwapESWithDS: 258 // Swap ES and DS 259 push es 260 push ds 261 pop es 262 pop ds 263 ret 264 265ExtReadGroupDescriptor: 266 mov eax, dword ptr BP_REL(ExtReadInodeGroupBlock) // Get Inode group block 267 add eax, dword ptr BP_REL(ExtFirstDataBlock) // Add the Group Descriptor offset 268 call ExtSetInodeSegment 269 270ExtReadBlock: 271 xor edx, edx 272 mov ecx, dword ptr BP_REL(ExtBlockSize) 273 mul ecx 274 jmp ReadSectors 275 276// EAX 277ExtCalculateBlock: 278 xor edx, edx // Clear EDX before division 279 div dword ptr BP_REL(ExtBlockSizeInBytes) // Inode /= ExtBlockSizeInBytes 280 mov dword ptr ds:[bp + si], eax // Store the Inode block 281 ret 282 283// SI, DI 284ExtCalculateOffset: 285 add bx, bp // Sum BX with BP for absolute address 286 xor edx, edx // Clear EDX before multiplication 287 mov eax, dword ptr ds:[bp + si] // Get the Inode block 288 mul dword ptr BP_REL(ExtBlockSizeInBytes) // Inode *= ExtBlockSizeInBytes 289 mov ecx, dword ptr ds:[bx] // Get the Inode 290 sub ecx, eax // Subtract the original Inode with rounded down Inode 291 mov word ptr ds:[bp + di], cx // Store the rounded down Inode 292 ret 293 294ExtSetOldFileSegment: 295 mov ebx, dword ptr BP_REL(ExtFileAddressOld) // Get the EXT old file address 296 jmp .ExtSegSkip 297ExtSetFileSegment: 298 mov ebx, dword ptr BP_REL(ExtFileAddress) // Get the EXT file address 299.ExtSegSkip: 300 shr ebx, 4 // Shift four bits to the right to get segment 301 jmp .ExtSkip 302ExtSetInodeSegment: 303 mov bx, EXT_INODE_ADDRESS / 16 // Get the EXT inode address 304.ExtSkip: 305 mov es, bx // Set ES 306 xor bx, bx // Clear BX 307 ret 308 309// Read the Inode in EAX register 310ExtReadInode: 311 xor edx, edx // Clear EDX before division 312 dec eax // Inode-- 313 div dword ptr BP_REL(ExtInodesPerGroup) // Inode /= ExtInodesPerGroup 314 mov dword ptr BP_REL(ExtReadInodeGroup), eax // Store the Inode group 315 mov dword ptr BP_REL(ExtReadInodeIndex), edx // Store the Inode index 316 317 xor edx, edx // Clear EDX before multiplication 318 mul dword ptr BP_REL(ExtGroupDescSize) // Inode group *= ExtGroupDescSize 319 mov dword ptr BP_REL(ExtReadInodeGroup), eax // Store the precalculated Inode group 320 321 xor edx, edx // Clear EDX before multiplication 322 mov eax, dword ptr BP_REL(ExtReadInodeIndex) // Get the read Inode index 323 mul dword ptr BP_REL(ExtInodeSize) // Inode group *= ExtInodeSize 324 mov dword ptr BP_REL(ExtReadInodeIndex), eax // Store the Inode index 325 326 // Calculate the Inode index block 327 mov si, offset ExtReadInodeIndexBlock - start 328 call ExtCalculateBlock 329 330 // Calculate the Inode group block 331 mov eax, dword ptr BP_REL(ExtReadInodeGroup) 332 mov si, offset ExtReadInodeGroupBlock - start 333 call ExtCalculateBlock 334 335 // Calculate the Inode group offset 336 mov bx, offset ExtReadInodeGroup - start 337 mov si, offset ExtReadInodeGroupBlock - start 338 mov di, offset ExtReadInodeGroupOffset - start 339 call ExtCalculateOffset 340 341 // Calculate the Inode index offset 342 mov bx, offset ExtReadInodeIndex - start 343 mov si, offset ExtReadInodeIndexBlock - start 344 mov di, offset ExtReadInodeIndexOffset - start 345 call ExtCalculateOffset 346 347 // Read group descriptor 348 call ExtReadGroupDescriptor 349 350 // Set the offset address 351 mov si, word ptr BP_REL(ExtReadInodeGroupOffset) 352 353 // Get InodeTable field from the ExtGroupDescriptor structure 354 mov eax, dword ptr es:[si + EXT_GROUP_DESC_INODE_TABLE_OFFSET] 355 356 // Sum EAX with Inode index block 357 add eax, dword ptr BP_REL(ExtReadInodeIndexBlock) 358 359 jmp ExtReadBlock 360 361msgDiskError: 362 .ascii "Disk error", CR, LF, NUL 363msgAnyKey: 364 .ascii "Press any key", CR, LF, NUL 365 366.org 509 367 368BootPartition: 369 .byte 0 370 371.word HEX(AA55) // BootSector signature 372 373// End of bootsector 374// 375// Now starts the extra boot code that we will store 376// at sector 1 on a EXT volume 377 378LoadRootDirectory: 379 mov al, EXT_ROOT_INODE // Put the root directory inode number in AL 380 movzx eax, al // Convert AL to EAX 381 382 call ExtReadInode // Read the inode 383 call BasicReadFile // Load the directory entries using basic function 384 call SearchFile // Find the extended loader and run it 385 386 jmp ExtLdrPrintFileNotFound // If the extended loader wasn't found, display an error 387 388ExtInodeDetectExtentsFlag: 389 mov eax, es:[si + EXT_INODE_FLAGS_OFFSET] 390 test eax, EXT_INODE_FLAG_EXTENTS 391 ret 392 393ExtUpdateFileSize: 394 mov eax, dword ptr BP_REL(ExtBlockSizeInBytes) 395 396ExtAdjustFileSize: 397 // Update the file size 398 sub dword ptr BP_REL(ExtFileSizeState), eax 399 add dword ptr BP_REL(ExtFileAddress), eax 400 ret 401 402ExtReadFileDone: 403 push eax 404 mov eax, dword ptr BP_REL(ExtFileSizeState) 405 cmp eax, dword ptr BP_REL(ExtBlockSizeInBytes) 406 pop eax 407 ret 408 409ExtFileReadBlocks: 410 push es 411.FRLoop: 412 // Check if there is no more blocks to read 413 call ExtReadFileDone 414 jb .FRDone 415 416 // If the block count is zero then do nothing 417 test bx, bx 418 jz .FRDone 419 420 // Read the block 421 pushad 422 call ExtSetFileSegment 423 call ExtReadBlock 424 popad 425 426 // Update the file size 427 call ExtUpdateFileSize 428 429 // Go to the next block and decrement the block count 430 inc eax 431 dec bx 432 433 // Loop until all blocks are read 434 jmp .FRLoop 435.FRDone: 436 pop es 437 ret 438 439BasicReadFileExtents: 440 // Add block pointer offset 441 add si, EXT_INODE_BLOCK_POINTER_OFFSET 442 443.DepthExtentsLoop: 444 // Load extent header depth 445 mov dx, word ptr es:[si + EXT_EXTENT_HEADER_DEPTH_OFFSET] 446 447 // Check if depth is zero 448 test dx, dx 449 jz .DepthExtentsDone 450 451 // Go to next extent 452 add si, EXT_EXTENT_SIZE 453 454 // Push all registers 455 pushad 456 457 // Read the extent block 458 mov eax, dword ptr es:[si + EXT_EXTENT_INDEX_LEAF_OFFSET] 459 call ExtSetInodeSegment 460 call ExtReadBlock 461 462 // Pop all registers 463 popad 464 465 // Reset SI 466 xor si, si 467 468 jmp .DepthExtentsLoop 469.DepthExtentsDone: 470 // Load extent header entries 471 mov cx, word ptr es:[si + EXT_EXTENT_HEADER_ENTRIES_OFFSET] 472 473.FinalExtentsLoop: 474 // Check if there is no more blocks to read 475 call ExtReadFileDone 476 jb .FinalExtentsDone 477 478 // Go to next extent 479 add si, EXT_EXTENT_SIZE 480 481 // Load extent length 482 mov bx, word ptr es:[si + EXT_EXTENT_LENGTH_OFFSET] 483 and ebx, HEX(FFFF) 484 485 // Check if extent is sparse 486 cmp bx, EXT_EXTENT_MAX_LENGTH 487 jbe .NotSparse 488 489 // Adjust sparse extent length 490 sub bx, EXT_EXTENT_MAX_LENGTH 491 492 // Adjust extent length to byte count 493 // by multiplying extent length to block size 494 xor edx, edx 495 mov eax, dword ptr BP_REL(ExtBlockSizeInBytes) 496 mul ebx 497 498 // Adjust file size for sparse extent 499 call ExtAdjustFileSize 500 501 jmp .FinalExtentsSkip 502 503.NotSparse: 504 // Read blocks from extent start 505 mov eax, dword ptr es:[si + EXT_EXTENT_START_OFFSET] 506 call ExtFileReadBlocks 507 508.FinalExtentsSkip: 509 // Loop to process next extent 510 loop .FinalExtentsLoop 511 512.FinalExtentsDone: 513 ret 514 515BasicReadFile: 516 push es 517 pushad 518 call ExtSetInodeSegment 519 520 // Set the correct Inode offset 521 mov si, word ptr BP_REL(ExtReadInodeIndexOffset) 522 523 // Set the old file address 524 mov eax, dword ptr BP_REL(ExtFileAddress) 525 mov dword ptr BP_REL(ExtFileAddressOld), eax 526 527 // Set the file size limit 528 mov eax, EXT_INODE_DATA_SIZE_LIMIT 529 530 // Load file size from Inode 531 mov ebx, dword ptr es:[si + EXT_INODE_SIZE_OFFSET] 532 533 // Compare and limit file size 534 cmp ebx, eax 535 jbe .BelowOrEqualSize 536 mov ebx, eax 537.BelowOrEqualSize: 538 // Store the file size in the ExtFileSize variable 539 mov dword ptr BP_REL(ExtFileSize), ebx 540 541 // Set rounded up file size 542 add ebx, dword ptr BP_REL(ExtBlockSizeInBytes) 543 dec ebx 544 mov dword ptr BP_REL(ExtFileSizeState), ebx 545 546 // Don't use the extents method if theres no extents flag 547 call ExtInodeDetectExtentsFlag 548 jz .NoExtents 549 550 // If this Inode use Extents mapping then use the extents method and skip the entire classic method 551 call BasicReadFileExtents 552 jmp .LDone 553 554.NoExtents: 555 // Set up for reading direct block addresses 556 xor ecx, ecx 557 mov cl, EXT_INODE_BLOCKS 558 add si, EXT_INODE_BLOCK_POINTER_OFFSET 559.LLoop: 560 call ExtSetInodeSegment 561 562 call ExtReadFileDone 563 jb .LDone 564 565 // Get the block address 566 mov eax, dword ptr es:[si] 567 568 // If the block address is zero, skip the block 569 test eax, eax 570 jz .LSkipBlock 571 572 // Set the file segment 573 call ExtSetFileSegment 574 575 // Read the block 576 call ExtReadBlock 577.LSkipBlock: 578 call ExtUpdateFileSize 579 580 // Increment block 581 add si, EXT_POINTER_SIZE 582 583 // Loop until all blocks are loaded 584 loop .LLoop 585.LDone: 586 popad 587 pop es 588 ret 589 590SearchFile: 591 call ExtSetOldFileSegment 592 call SwapESWithDS 593 594 xor si, si 595 mov dx, word ptr BP_REL(ExtFileSize) 596.FLoop: 597 mov eax, dword ptr ds:[si] // Load directory Inode 598 599 cmp si, dx // End of buffer reached? 600 jae .Done // Abort the search if yes 601 602 // Save SI 603 push si 604 605 test eax, eax // Check if Inode is zero 606 jz .Skip // Skip this entry if yes 607 608 mov di, offset ExtLdrFileName // Load target filename address 609 mov cx, offset ExtLdrFileNameEnd - ExtLdrFileName // Length of filename to compare 610 cmp byte ptr ds:[si + EXT_DIRECTORY_ENTRY_NAME_LENGTH_OFFSET], cl // Compare if both names have the same length 611 jnz .Skip // Skip this entry if not 612 add si, EXT_DIRECTORY_ENTRY_NAME_OFFSET // Move to filename in entry 613 repe cmpsb // Compare filenames 614 pop si // Restore SI 615 jz LoadExtLdr // Found matching file 616 push si // Save SI 617 618.Skip: 619 // Restore SI 620 pop si 621 622 // Move to next directory entry and continue looping 623 add si, word ptr ds:[si + EXT_DIRECTORY_ENTRY_SIZE_OFFSET] 624 jmp .FLoop 625.Done: 626 ret 627 628LoadExtLdr: 629 // Swap ES and DS 630 call SwapESWithDS 631 632 push si // Save SI 633 mov si, offset msgLoadingExtLdr // Point SI to a loading message 634 call PutChars // Show the message 635 pop si // Restore SI 636 637 mov eax, dword ptr es:[si] // Load directory Inode 638 call ExtReadInode // Read the inode 639 mov si, word ptr BP_REL(ExtReadInodeIndexOffset) // Set the correct offset 640 641 // Get Inode type 642 mov ax, word ptr es:[si] 643 and ax, EXT_INODE_TYPE_MASK 644 645 cmp ax, EXT_INODE_TYPE_REGULAR // Check if regular file 646 jnz ExtLdrPrintRegFileError // If not, handle error 647 648 call BasicReadFile // Load the file using basic function 649 call ExtSetOldFileSegment // Set old file segment 650 call SwapESWithDS // Swap ES with DS before copy 651 652 // Copy the loaded file to 1KB ahead of this bootsector 653 xor si, si 654 mov di, offset ExtLdrEntryPoint 655 mov cx, EXTLDR_BOOTSECTOR_SIZE 656 rep movsb 657 658 ljmp16 0, ExtLdrEntryPoint 659 660ExtLdrPrintFileNotFound: 661 // Make DS correct, display it and reboot 662 call SwapESWithDS 663 mov si, offset msgExtLdr 664 jmp DisplayItAndReboot 665 666ExtLdrPrintRegFileError: 667 mov si, offset msgExtLdrNotRegularFile // ExtLdr not found message 668DisplayItAndReboot: 669 call PutChars // Display it 670 jmp Reboot 671 672ExtLdrFileName: 673 .ascii "extldr.sys" 674ExtLdrFileNameEnd: 675 676msgExtLdr: 677 .ascii "extldr.sys not found", CR, LF, NUL 678msgExtLdrNotRegularFile: 679 .ascii "extldr.sys is not a regular file", CR, LF, NUL 680msgLoadingExtLdr: 681 .ascii "Loading ExtLoader...", CR, LF, NUL 682 683.org 1022 684 685.word HEX(AA55) // BootSector signature 686 687ExtLdrEntryPoint: 688// ExtLdr is loaded here 689 690.endcode16 691 692END 693 694#else 695 696#define start BOOTSECTOR_BASE_ADDRESS 697 698#define BootDrive (start + 3) 699#define ExtVolumeStartSector (BootDrive + 1) 700#define ExtBlockSize (ExtVolumeStartSector + 4) 701#define ExtBlockSizeInBytes (ExtBlockSize + 4) 702#define ExtPointersPerBlock (ExtBlockSizeInBytes + 4) 703#define ExtGroupDescSize (ExtPointersPerBlock + 4) 704#define ExtFirstDataBlock (ExtGroupDescSize + 4) 705#define ExtInodeSize (ExtFirstDataBlock + 4) 706#define ExtInodesPerGroup (ExtInodeSize + 4) 707 708#define ExtFileSize (ExtInodesPerGroup + 4) 709#define ExtFileAddress (ExtFileSize + 4) 710#define ExtFileAddressOld (ExtFileAddress + 4) 711 712#define ExtReadInodeGroup (ExtFileAddressOld + 4) 713#define ExtReadInodeIndex (ExtReadInodeGroup + 4) 714#define ExtReadInodeGroupBlock (ExtReadInodeIndex + 4) 715#define ExtReadInodeIndexBlock (ExtReadInodeGroupBlock + 4) 716#define ExtReadInodeGroupOffset (ExtReadInodeIndexBlock + 4) 717#define ExtReadInodeIndexOffset (ExtReadInodeGroupOffset + 2) 718 719#define BootPartition (BootDrive + 506) 720 721#define ExtReadBlock word ptr ss:[bp-ExtReadBlockOffset] 722#define ExtReadInode word ptr ss:[bp-ExtReadInodeOffset] 723#define DisplayItAndReboot word ptr ss:[bp-DisplayItAndRebootOffset] 724#define PutChars word ptr ss:[bp-PutCharsOffset] 725 726#endif