137 lines
4.5 KiB
NASM
137 lines
4.5 KiB
NASM
; limlz: Copyright (C) 2026 Kamila Szewczyk <k@iczelia.net>
|
|
; limine: Copyright (C) 2019-2026 Mintsuki and contributors.
|
|
;
|
|
; Redistribution and use in source and binary forms, with or without
|
|
; modification, are permitted provided that the following conditions are met:
|
|
;
|
|
; 1. Redistributions of source code must retain the above copyright notice, this
|
|
; list of conditions and the following disclaimer.
|
|
;
|
|
; 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
; this list of conditions and the following disclaimer in the documentation
|
|
; and/or other materials provided with the distribution.
|
|
;
|
|
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
; CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
org 0x70000
|
|
bits 32
|
|
|
|
global _start
|
|
_start:
|
|
cld
|
|
; On stack (cdecl): [esp+4]=compressed_stage2, [esp+8]=stage2_size,
|
|
; [esp+12]=boot_drive (byte), [esp+16]=pxe
|
|
mov ebx, dword [esp+0x4] ; compressed_stage2
|
|
mov ebp, dword [ebx] ; expected_crc = *(uint32_t *)compressed_stage2
|
|
lea edx, [ebx+0x4] ; ip = compressed_stage2 + 4
|
|
add ebx, dword [esp+0x8] ; ipe = compressed_stage2 + stage2_size
|
|
mov edi, 0xf000 ; op = dest
|
|
; LZ decompression loop
|
|
.Ltoken:
|
|
movzx ecx, byte [edx]
|
|
lea esi, [edx+0x1]
|
|
mov eax, ecx ; save token
|
|
shr ecx, 0x3
|
|
and ecx, 0xf ; literal length = (token >> 3) & 15
|
|
cmp ecx, 0xf
|
|
jne .Llitcopy
|
|
movzx ecx, byte [edx+0x1]
|
|
lea esi, [edx+0x2]
|
|
add ecx, 0xf ; length += extra byte + 15
|
|
.Llitcopy:
|
|
rep movsb ; copy literals
|
|
cmp esi, ebx
|
|
jae .Lcrc ; if ip >= ipe, done
|
|
test al, al
|
|
jns .Loffset1 ; bit 7 clear => 1-byte offset
|
|
lea edx, [esi+0x2]
|
|
movzx esi, word [esi] ; 2-byte offset
|
|
jmp .Lmatchlen
|
|
.Loffset1:
|
|
lea edx, [esi+0x1]
|
|
movzx esi, byte [esi] ; 1-byte offset
|
|
.Lmatchlen:
|
|
and al, 0x7
|
|
cmp al, 0x7
|
|
je .Lmatchextra
|
|
movzx eax, al
|
|
jmp .Ldomatch
|
|
.Lmatchextra:
|
|
movzx eax, byte [edx]
|
|
inc edx
|
|
add eax, 0x7 ; matchlen += extra byte + 7
|
|
.Ldomatch:
|
|
mov ecx, edi
|
|
sub ecx, esi ; match = op - offset
|
|
mov esi, ecx
|
|
lea ecx, [eax+0x4] ; count = matchlen + 4
|
|
rep movsb ; copy match
|
|
cmp edx, ebx ; guard against streams that end on a match
|
|
jae .Lcrc
|
|
jmp .Ltoken
|
|
; CRC32 verification
|
|
.Lcrc:
|
|
mov edx, 0xf000 ; ptr = dest
|
|
mov esi, edx ; (also reused for esp later)
|
|
xor eax, eax
|
|
dec eax
|
|
.Lcrc_byte:
|
|
cmp edx, edi
|
|
je .Lcrc_done
|
|
lea ecx, [edx+0x1]
|
|
movzx edx, byte [edx]
|
|
xor eax, edx
|
|
push 0x08
|
|
pop edx ; 8 bits per byte
|
|
.Lcrc_bit:
|
|
mov ebx, eax
|
|
and eax, 0x1
|
|
shr ebx, 1
|
|
neg eax
|
|
and eax, 0xedb88320
|
|
xor eax, ebx
|
|
dec edx
|
|
jne .Lcrc_bit
|
|
mov edx, ecx
|
|
jmp .Lcrc_byte
|
|
.Lcrc_done:
|
|
not eax
|
|
cmp eax, ebp
|
|
jne .Lerror
|
|
; Jump to decompressed stage2
|
|
movzx eax, byte [esp+0xc] ; boot_drive
|
|
mov ecx, dword [esp+0x10] ; pxe
|
|
mov esp, esi
|
|
xor ebp, ebp
|
|
push ecx
|
|
push eax
|
|
push ebp
|
|
push esi
|
|
ret ; jump to 0xf000
|
|
; Error: display message and cli/hlt
|
|
.Lerror:
|
|
mov edx, errmsg
|
|
mov eax, 0xb8000
|
|
.Lerror_loop:
|
|
movzx ecx, byte [edx]
|
|
add eax, 0x2
|
|
inc edx
|
|
or ch, 0x4f
|
|
mov word [eax-0x2], cx
|
|
cmp eax, 0xB8000 + errmsg.len * 2
|
|
jne .Lerror_loop
|
|
cli
|
|
hlt
|
|
|
|
errmsg: db "limine integrity error"
|
|
.len: equ $ - errmsg
|