:: limine / stage1 / decompressor.asm 4.5 KB raw

1
; limlz: Copyright (C) 2026 Kamila Szewczyk <k@iczelia.net>
2
; limine: Copyright (C) 2019-2026 Mintsuki and contributors.
3
; 
4
; Redistribution and use in source and binary forms, with or without
5
; modification, are permitted provided that the following conditions are met:
6
; 
7
; 1. Redistributions of source code must retain the above copyright notice, this
8
;    list of conditions and the following disclaimer.
9
; 
10
; 2. Redistributions in binary form must reproduce the above copyright notice,
11
;    this list of conditions and the following disclaimer in the documentation
12
;    and/or other materials provided with the distribution.
13
; 
14
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15
; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18
; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20
; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21
; CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22
; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
25
org 0x70000
26
bits 32
27
28
global _start
29
_start:
30
    cld
31
    ; On stack (cdecl): [esp+4]=compressed_stage2, [esp+8]=stage2_size,
32
    ;                   [esp+12]=boot_drive (byte), [esp+16]=pxe
33
    mov    ebx, dword [esp+0x4]      ; compressed_stage2
34
    mov    ebp, dword [ebx]          ; expected_crc = *(uint32_t *)compressed_stage2
35
    lea    edx, [ebx+0x4]            ; ip = compressed_stage2 + 4
36
    add    ebx, dword [esp+0x8]      ; ipe = compressed_stage2 + stage2_size
37
    mov    edi, 0xf000               ; op = dest
38
    ; LZ decompression loop
39
.Ltoken:
40
    movzx  ecx, byte [edx]
41
    lea    esi, [edx+0x1]
42
    mov    eax, ecx                  ; save token
43
    shr    ecx, 0x3
44
    and    ecx, 0xf                  ; literal length = (token >> 3) & 15
45
    cmp    ecx, 0xf
46
    jne    .Llitcopy
47
    movzx  ecx, byte [edx+0x1]
48
    lea    esi, [edx+0x2]
49
    add    ecx, 0xf                  ; length += extra byte + 15
50
.Llitcopy:
51
    rep    movsb                     ; copy literals
52
    cmp    esi, ebx
53
    jae    .Lcrc                     ; if ip >= ipe, done
54
    test   al, al
55
    jns    .Loffset1                 ; bit 7 clear => 1-byte offset
56
    lea    edx, [esi+0x2]
57
    movzx  esi, word [esi]           ; 2-byte offset
58
    jmp    .Lmatchlen
59
.Loffset1:
60
    lea    edx, [esi+0x1]
61
    movzx  esi, byte [esi]           ; 1-byte offset
62
.Lmatchlen:
63
    and    al, 0x7
64
    cmp    al, 0x7
65
    je     .Lmatchextra
66
    movzx  eax, al
67
    jmp    .Ldomatch
68
.Lmatchextra:
69
    movzx  eax, byte [edx]
70
    inc    edx
71
    add    eax, 0x7                  ; matchlen += extra byte + 7
72
.Ldomatch:
73
    mov    ecx, edi
74
    sub    ecx, esi                  ; match = op - offset
75
    mov    esi, ecx
76
    lea    ecx, [eax+0x4]            ; count = matchlen + 4
77
    rep    movsb                     ; copy match
78
    cmp    edx, ebx                  ; guard against streams that end on a match
79
    jae    .Lcrc
80
    jmp    .Ltoken
81
    ; CRC32 verification
82
.Lcrc:
83
    mov    edx, 0xf000               ; ptr = dest
84
    mov    esi, edx                  ; (also reused for esp later)
85
    xor    eax, eax
86
    dec    eax
87
.Lcrc_byte:
88
    cmp    edx, edi
89
    je     .Lcrc_done
90
    lea    ecx, [edx+0x1]
91
    movzx  edx, byte [edx]
92
    xor    eax, edx
93
    push   0x08
94
    pop    edx                       ; 8 bits per byte
95
.Lcrc_bit:
96
    mov    ebx, eax
97
    and    eax, 0x1
98
    shr    ebx, 1
99
    neg    eax
100
    and    eax, 0xedb88320
101
    xor    eax, ebx
102
    dec    edx
103
    jne    .Lcrc_bit
104
    mov    edx, ecx
105
    jmp    .Lcrc_byte
106
.Lcrc_done:
107
    not    eax
108
    cmp    eax, ebp
109
    jne    .Lerror
110
    ; Jump to decompressed stage2
111
    movzx  eax, byte [esp+0xc]       ; boot_drive
112
    mov    ecx, dword [esp+0x10]     ; pxe
113
    mov    esp, esi
114
    xor    ebp, ebp
115
    push   ecx
116
    push   eax
117
    push   ebp
118
    push   esi
119
    ret                              ; jump to 0xf000
120
    ; Error: display message and cli/hlt
121
.Lerror:
122
    mov    edx, errmsg
123
    mov    eax, 0xb8000
124
.Lerror_loop:
125
    movzx  ecx, byte [edx]
126
    add    eax, 0x2
127
    inc    edx
128
    or     ch, 0x4f
129
    mov    word [eax-0x2], cx
130
    cmp    eax, 0xB8000 + errmsg.len * 2
131
    jne    .Lerror_loop
132
    cli
133
    hlt
134
135
errmsg: db "limine integrity error"
136
.len: equ $ - errmsg
tab: 248 wrap: offon