xref: /reactos/boot/freeldr/bootsect/isombr.S (revision c2c66aff)
1/*
2 * PROJECT:     ReactOS MBR Boot Sector for ISO file system ("isohybrid mode")
3 * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE:     Providing an MBR Boot Sector that enables an ISO to be booted from a disk
5 * COPYRIGHT:   Copyright 2017 Colin Finck (colin@reactos.org)
6 */
7
8#include <asm.inc>
9
10.code16
11
12// The "isohybrid" tool patching our ISO will write the LBA of the El Torito BIOS Boot Sector to this address.
13pBootSectorLBA = start+432
14
15// Our BIOS Boot Sector contains this signature at the specified position and our third-party imported "isohybrid" patching tool checks for it.
16// This is also why it's the same signature ISOLINUX uses.
17HybridSignature = HEX(7078C0FB)
18pBootSectorHybridSignature = HEX(7C00)+64
19pBootSectorHybridEntryPoint = HEX(7C00)+64+4
20
21start:
22    // The MBR needs to start with 33h, because some dumb BIOSes check for that (cf. syslinux commit d0f275981c9289dc4b8df64e72cd9902bf85aebe).
23    // The following line encodes a "xor ax, ax" (but it's not the only way to encode it, so we can't just write that instruction here).
24    .byte HEX(33), HEX(C0)
25
26    // Set up our stack and a flat addressing model.
27    cli
28    mov ss, ax
29    mov sp, offset start
30    mov ds, ax
31    mov es, ax
32    mov fs, ax
33    mov gs, ax
34    sti
35
36    // Our boot sector has been loaded to address 0x7C00.
37    // Relocate our 512 bytes boot sector to the given base address (should be 0x7000).
38    cld
39    mov cx, 512 / 4
40    mov si, HEX(7C00)
41    mov di, offset start
42    rep movsd
43
44    // Jump to the relocated code.
45    ljmp16 0, relocated
46
47relocated:
48    // Prepare the Disk Access Packet (DAP) for INT 13h, Function 42h: Extended Read Sectors from Drive.
49    // Read 4 sectors to address 7C00h, which is exactly our 2K-sized BIOS Boot Sector.
50    push 0
51    push 0
52    push dword ptr es:[pBootSectorLBA]
53    push es
54    push HEX(7C00)
55    push 4
56    push HEX(10)
57
58    // Call the BIOS function. Note that we haven't clobbered DL up to this point, so the Drive Number passed by the BIOS is still there.
59    // Read errors are indicated by the Carry Flag.
60    mov ah, HEX(42)
61    mov si, sp
62    int HEX(13)
63    jc read_error
64
65    // Verify the Hybrid Signature.
66    cmp dword ptr es:[pBootSectorHybridSignature], HybridSignature
67    jne invalid_signature
68
69    // Signature is valid, so jump to the entry point for the hybrid code.
70    ljmp16 0, pBootSectorHybridEntryPoint
71
72read_error:
73    call die_with_error
74    .ascii "ISOMBR: Read Error!", CR, LF
75
76invalid_signature:
77    call die_with_error
78    .ascii "ISOMBR: Invalid Boot Sector Hybrid Signature!", CR, LF
79
80die_with_error:
81    // Fetch the message to output stored at the return address on the stack.
82    pop si
83
84    // Call BIOS INT 10h, Function 0Eh to output a single character.
85    // Do this in a loop and stop after we have printed the newline LF character.
86next_character:
87    lodsb
88    mov ah, HEX(0E)
89    xor bx, bx
90    int HEX(10)
91    cmp al, 10
92    jne next_character
93
94    // Die gracefully, that means in an infinite HLT loop to not put any stress on the CPU.
95die:
96    hlt
97    jmp die
98
99// The "isohybrid" tool will add the remaining information, including the infamous 0xAA55 MBR signature.
100.org 431
101    .byte 0
102
103.endcode16
104
105END
106